题目
给定两个字符串 s
和 t
,编写一个函数来判断 t
是否是 s
的 字母异位词。
示例 1:
输入: s = "anagram", t = "nagaram" 输出: true
示例 2:
输入: s = "rat", t = "car" 输出: false
提示:
1 <= s.length, t.length <= 5 * 104
s
和t
仅包含小写字母
进阶: 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?
详解
异或法
首先看到这个题目就想起来了刚刚写过的异或运算:力扣389.找不同-优快云博客
所以这一题是不是也可以直接异或看结果是否为0呢?就像这样:
class Solution {
public boolean isAnagram(String s, String t) {
char c = 0;
int len1 = s.length();
int len2 = t.length();
//记录len为len1、len2中最长的
int len = Math.max(len1,len2);
for (int i =0;i< len;i++){
if (i<len1){
c ^= s.charAt(i);
}
if (i<len2){
c ^= t.charAt(i);
}
}
if(c == 0){
return true;
}else {
return false;
}
}
}
提交结果发现
解答错误
41 / 52 个通过的测试用例
原因是
解法使用了异或运算来判断两个字符串是否是字母异位词,这种方法在某些情况下可能会出错。具体来说,如果两个字符串长度相同,并且它们的字符异或结果为0,那么它们有可能是字母异位词。然而,这种判断方法不够严谨,因为不同的字符组合可能会导致相同的异或结果。
例如,考虑字符串 "ab" 和 "cc",它们的异或结果也是0,但它们并不是字母异位词。因此,这种方法存在误判的风险。
排序比较法
- 检查两个字符串的长度是否相同。如果不同,直接返回
false
。 - 将两个字符串的字符排序,然后比较排序后的结果是否相同。如果相同,则它们是字母异位词。
import java.util.Arrays;
class Solution {
public boolean isAnagram(String s, String t) {
if (s.length() != t.length()) {
return false;
}
char[] sArray = s.toCharArray();
char[] tArray = t.toCharArray();
Arrays.sort(sArray);
Arrays.sort(tArray);
return Arrays.equals(sArray, tArray);
}
}
Arrays.sort(sArray);此方法是排序的常用方法;
进阶
如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?
这个问题我也尝试了好久,发现上述排序比较法使用toCharArray()方法进行排序的时候,在某些特定的情况下会存在问题,特别是当字符串中包含Unicode补充字符(Supplementary Characters) 时,比如一些 emoji、罕见汉字、特殊符号等。
toCharArray 的适用场景(不会有问题)
-
普通英文字符(如
a-z
,A-Z
) -
常见的中日韩文字(位于 BMP,即基本多文种平面)
-
一般符号和数字(如
#
,1
,@
等)
可能出问题的场景:包含 Unicode 补充字符(> U+FFFF)
例如
String str = "a😊b"; char[] chars = str.toCharArray(); System.out.println(Arrays.toString(chars));
输出为:
[a, \ud83d, \ude0a, b]
-
😊
(Unicode U+1F60A)被拆成两个 char:\ud83d
和\ude0a
(代理对)。 -
排序后可能变成:
\ude0a
,a
,b
,\ud83d
—— 导致字符显示异常甚至乱码。
推荐方案(安全排序方式)
int[] codePoints = str.codePoints().toArray();
Arrays.sort(codePoints);
String sorted = new String(codePoints, 0, codePoints.length);
System.out.println(sorted);
这个方案能正确识别和排序所有字符,不会破坏 emoji 等特殊字符。
总结
方法 | 能否安全排序包含 Unicode 的字符串 | 说明 |
---|---|---|
toCharArray() + Arrays.sort() | ❌ 不推荐 | 会拆开代理对,造成错误排序或乱码 |
codePoints() + Arrays.sort() | ✅ 推荐 | 正确处理所有 Unicode 字符,包括 emoji |
如果只处理英文和常见中文,用 toCharArray()
没问题;如果你要考虑 emoji、特殊符号或国际化,务必用 codePoints()
。