学习目标:
本次学习目标为 力扣初级算法-字符串,其中主要的LC如下:
- 有效的字母异位词
学习内容:
- 有效的字母异位词-----(链接)
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。示例1:
输入: s = “anagram”, t = “nagaram”
输出: true
示例2:
输入: s = “rat”, t = “car”
输出: false说明: s 和 t 仅包含小写字母
解题思路:
-
解法一: 三次循环
-
边界问题:入参字符s与入参字符t的长度不一致
-
代码逻辑过程:
- 声明用于存放 统计字符出现次数的字符数组,为节省空间,将单个字符转换为数字,同时又因为英文字母一共有26位,故只申请长度位26的字符数组即可,将数组下标作为字母字符,数组下标的元素值作为 出现的次数
- 循环统计入参s的字符出现次数
- 循环统计入参t的字符出现次数,当若当前元素在统计的 charArray 未出现,则此时可以直接跳出,返回FALSE,同时要考虑入参s 和 入参t 都有出现,但是次数不一样的问题,故当前循环,出现过得,需对 charArray 做减法
-
代码实现:
// 解法一:三次循环
public static boolean isAnagram01(String s, String t) {
// 0.边界问题: 入参字符长度不一致,直接返回 FALSE
if (s.length() != t.length()) {
return false;
}
// 声明用于存放 统计字符出现次数的字符数组,为节省空间,
// 将单个字符转换为数字,同时又因为英文字母一共有26位,故只申请长度位26的字符数组即可
// 将数组下标作为字母字符,数组下标的元素值作为 出现的次数
int[] charArray = new int[26];
// 循环统计入参s的字符出现次数
for (int i = 0; i < s.length(); i++) {
charArray[s.charAt(i) - 'a']++;
}
// 循环统计入参t的字符出现次数,当若当前元素在统计的 charArray 未出现,则此时可以直接跳出,返回FALSE
// 同时要考虑入参s 和 入参t 都有出现,但是次数不一样的问题,故当前循环,出现过得,需对 charArray 做减法
for (int i = 0; i < t.length(); i++) {
if (charArray[t.charAt(i) - 'a'] == 0) {
return false;
}
charArray[t.charAt(i) - 'a']--;
}
return true;
}
- 解法二: 排序后比较
- 边界问题:入参字符s与入参字符t的长度不一致
- 代码逻辑过程:
- 先对入参字符s 和 t,转换为 字符数组,然后再对两数组中的元素进行比较。
- 此处是用了java封装好的工具方法。
- 代码实现:
// 解法二: 排序后比较数组
public static boolean isAnagram02(String s, String t) {
char[] charOfS = s.toCharArray();
char[] charOfT = t.toCharArray();
Arrays.sort(charOfS);
Arrays.sort(charOfT);
// 排序后直接比较
return Arrays.equals(charOfS, charOfT);
}
// Arrays.equals 原生的方法
public static boolean equals(char[] a, char[] a2) {
if (a==a2)
return true;
if (a==null || a2==null)
return false;
int length = a.length;
if (a2.length != length)
return false;
for (int i=0; i<length; i++)
if (a[i] != a2[i])
return false;
return true;
}
- 解法三:单次循环比较
- 边界问题:入参字符s与入参字符t的长度不一致
- 代码逻辑过程:
- 先对入参字符s 和 t,转换为 字符数组
- 声明 count 作为统计字符出现次数不一致的数量,声明 int[] charArray 作为统计 英文字母出现的次数,其中 charArray 的下标作为英文26位字母(0 代表为 a,1 代表位 b 等),charArray 下标对应的元素作为当前英文字母出现的次数。
- 循环遍历,遍历次数为入参字符串的的字符数,单次循环,分别直接get 入参s 和 入参t 的元素,其中, 当 charOfS 的元素出现一位,则在 charArray 上加一,charOfT 的元素出现一次,则在 charArray 上减一。同时,当往 charArray 加一后,需往 count 加一;当往 charArray 减一后,则需往 count 减一。
- 思考: 不一定要使用count统计,可将count 统计去掉,也可以在最后遍历 charArray 数组,当数组出现 元素不为 0 的情况,也可以判断元素出现的次数是不一致的。
- 最后,判断 count 是否等于0,即可知道入参s 和入参t 是否字母异位。
- 代码实现:
// 解法三: 单次遍历
// 思路: 同解法一类似,声明一个统计的 数组,入参s中出现过则加一,入参t出现过后则减一
public static boolean isAnagram03(String s, String t) {
// 0.边界问题: 入参字符长度不一致,直接返回 FALSE
if (s.length() != t.length()) {
return false;
}
int[] charArray = new int[26];
char[] charOfS = s.toCharArray();
char[] charOfT = t.toCharArray();
// 统计出现字符不一样的情况
int count = 0;
for (int i = 0; i < s.length(); i++) {
if (++charArray[charOfS[i] - 'a'] == 1) {
count++;
}
if (--charArray[charOfT[i] - 'a'] == 0) {
count--;
}
}
return count == 0;
}