t 是 s 的变位词等价于「两个字符串不相等且两个字符串排序后相等」。首先判断字符串 s 和 t 是否相等,如果相等则直接返回 false,如果不相等则继续判断两个字符串排序后是否相等。我们可以对字符串 s 和 t 分别排序,看排序后的字符串是否相等。此外,如果 s 和 t 的长度不同,t 必然不是 s 的变位词。
从另一个角度考虑,t 是 s 的变位词等价于「两个字符串不相等且两个字符串中字符出现的种类和次数均相等」。首先判断字符串 s 和 t 是否相等,如果相等则直接返回 false,如果不相等则继续比较两个字符串中字符出现的种类和次数。由于字符串只包含 26 个小写字母,因此我们可以维护一个长度为 26 的频次数组 table,先遍历记录字符串 s 中字符出现的频次,然后遍历字符串 t,减去 table 中对应的频次,如果出现 table}[i]<0,则说明 t 包含一个不在 s 中的额外字符,返回 false 即可。
[sol2-Java]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
classSolution { publicbooleanisAnagram(String s, String t) { if (s.length() != t.length() || s.equals(t)) { returnfalse; } int[] table = newint[26]; for (inti=0; i < s.length(); i++) { table[s.charAt(i) - 'a']++; } for (inti=0; i < t.length(); i++) { table[t.charAt(i) - 'a']--; if (table[t.charAt(i) - 'a'] < 0) { returnfalse; } } returntrue; } }
[sol2-JavaScript]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
var isAnagram = function(s, t) { if (s.length !== t.length || s == t) { returnfalse; } const table = newArray(26).fill(0); for (let i = 0; i < s.length; ++i) { table[s.codePointAt(i) - 'a'.codePointAt(0)]++; } for (let i = 0; i < t.length; ++i) { table[t.codePointAt(i) - 'a'.codePointAt(0)]--; if (table[t.codePointAt(i) - 'a'.codePointAt(0)] < 0) { returnfalse; } } returntrue; };
funcisAnagram(s, t string)bool { if s == t { returnfalse } var c1, c2 [26]int for _, ch := range s { c1[ch-'a']++ } for _, ch := range t { c2[ch-'a']++ } return c1 == c2 }
[sol2-C]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
boolisAnagram(char* s, char* t) { if (len_s != len_t || strcmp(s, t) == 0) { returnfalse; } int table[26]; memset(table, 0, sizeof(table)); for (int i = 0; i < len_s; ++i) { table[s[i] - 'a']++; } for (int i = 0; i < len_t; ++i) { table[t[i] - 'a']--; if (table[t[i] - 'a'] < 0) { returnfalse; } } returntrue; }
funcisAnagram(s, t string)bool { iflen(s) != len(t) || s == t { returnfalse } cnt := map[rune]int{} for _, ch := range s { cnt[ch]++ } for _, ch := range t { cnt[ch]-- if cnt[ch] < 0 { returnfalse } } returntrue }