在 javascript 中理解 Valid Anagram 的解决方案
understanding solution of Valid Anagram in javascript
这是来自 LeetCode - Valid Anagram
给定两个字符串 s 和 t ,编写一个函数来确定 t 是否是 s 的变位词。
示例 1:
输入:s = "anagram", t = "nagaram"
输出:真
示例 2:
您可以假设该字符串仅包含小写字母。
跟进:
如果输入包含 unicode 字符怎么办?你会如何调整你的解决方案以适应这种情况?
我不明白下面这些代码
- 结果 1[s.charCodeAt(i) - 97]++; --> ++ 是什么意思?
- result2.length = 26; --> 26 代表什么?
- result2.fill(0); --> 为什么用 0 填充它?
请指教!
var isAnagram = function(s,t) {
if (s.length !== t.length)
result false;
const result1 = [];
result1.length = 26;
result1.fill(0);
const result2 = [];
result2.length = 26;
result2.fill(0);
for (let i = 0; i < s.length; i++) {
result1[s.charCodeAt(i) - 97]++;
result2[t.charCodeAt(i) - 97]++;
}
for (let i = 0; i < result1.length; i++) {
if (result1[i] !== result2[i]) {
return false;
}
}
return true;
};
++ 是自增运算符。它可以是前缀 (++i) 或 post-固定 (i++)。在这种情况下,它是 post-固定的:result1[s.charCodeAt(i) - 97]++
,因此它将增加 result1[s.charCodeAt(i) - 97]
.
的值
26 只是字母表中的字母数(从 a 到 z)。
代码正在初始化这两个数组并fill
将它们设为 0,以便它可以将数组元素用作计数器。数组中的每个索引代表字母表中的一个字母,并存储该字母在字符串中出现的次数。
代码写得有点糟糕,让我们稍微改进一下,这样你的问题就自动消失了:
var isAnagram = function(string1, string2) {
if (string1.length !== string2.length)
return false; // here was a typo: result false
const alphabetLength = 26;
// returns an array of zeros (empty counters), each one per alphabet letter
const getAlphabetCounters = function() {
const counters = [];
counters.length = alphabetLength;
counters.fill(0);
return counters;
}
const countCharacter = function(c, counters) {
// zero for a, 25 for z
const position = c.charCodeAt(0) - 97;
counters[position]++;
}
const counters1 = getAlphabetCounters();
const counters2 = getAlphabetCounters();
for (let i = 0; i < string1.length; i++) {
countCharacter(string1[i], counters1);
countCharacter(string2[i], counters2);
}
for (let i = 0; i < counters1.length; i++) {
if (counters1[i] !== counters2[i]) {
return false;
}
}
return true;
};
但是使用这样的 "decremental" 方法可能是更好的主意:
var isAnagram = function(string1, string2) {
if (string1.length !== string2.length)
return false;
let letters1 = string1.split('');
let letters2 = string2.split('');
for (let letter of letters1) {
let position = letters2.indexOf(letter);
if(position == -1)
return false;
letters2.splice(position, 1);
}
return true;
};
或者如果一个人关心长字符串的性能,那么对其中的字母进行排序并直接比较是一种可行的方法。
这是我的解决方案版本。您甚至可以跳过末尾的 join(),因为您仍然可以比较两个数组。
const isAnagram = function(s, t) {
if (s.length !== t.length ) {
return false;
}
if (s.split('').sort().join('') === t.split('').sort().join('')) {
return true;
} else {
return false;
}
};
使用最少的数组函数和单个 for 循环
function anagram(str1, str2){
var isAnagram = true;
if(str1.length != str2.length){
isAnagram = false;
}else{
for(var i=0; i<str1.length;i++) {
if(!str2.includes(str1[i])){
isAnagram = false;
}
}
}
if(isAnagram){
console.log('string is anagram');
}else{
console.log('string is not anagram');
}
}
anagram('READ', 'DEAR');
var isAnagram = function(s, t) {
let sArr = s.split('');
let tArr = t.split('');
sArr.sort();
let newS = sArr.join('');
tArr.sort();
let newT = tArr.join('');
return newS === newT;
};
只需一行代码即可完成
const isAnagram = (s,t) => ( [...s].sort().join('') === [...t].sort().join(''))
console.log( isAnagram('anagram', 'nagaram') ) // true
console.log( isAnagram('anagram', 'xxx') ) // false
但是您的问题还要求管理所有 utf8 字符,我将其解释为必须消除 diacritic, for which there is an answer here.
我做了一些改动,只保留字母(不包括空格和其他标点符号),以便也能够处理几个单词的字谜:
const letters = str => str.toLowerCase().normalize("NFD").replace(/[^a-z]/g, '')
最终解决方案:
const letters = str => str.toLowerCase().normalize("NFD").replace(/[^a-z]/g, '')
, isAnagram = (s,t) => ( [...letters(s)].sort().join('') === [...letters(t)].sort().join(''))
;
const anagrams = // from wikipedia
[ { s: "evil"
, t: "vile" }
, { s: "New York Times"
, t: "monkeys write" }
, { s: "William Shakespeare"
, t: "I am a weakish speller" }
, { s: "Le commandant Cousteau"
, t: "Tout commença dans l'eau" } // with diacritic ( French )
, { s: "La crise économique"
, t: "Le scénario comique" }
, { s: "Question sans réponse"
, t: "Enquêtons sans espoir" }
, { s: "Chauve-souris"
, t: "Souche à virus" }
]
for (let {s,t} of anagrams )
console.log(`_${s}_, _${t}_ -> `, isAnagram(s,t))
.as-console-wrapper { max-height: 100% !important; top: 0; }
这是来自 LeetCode - Valid Anagram
给定两个字符串 s 和 t ,编写一个函数来确定 t 是否是 s 的变位词。
示例 1:
输入:s = "anagram", t = "nagaram"
输出:真
示例 2:
您可以假设该字符串仅包含小写字母。
跟进: 如果输入包含 unicode 字符怎么办?你会如何调整你的解决方案以适应这种情况?
我不明白下面这些代码
- 结果 1[s.charCodeAt(i) - 97]++; --> ++ 是什么意思?
- result2.length = 26; --> 26 代表什么?
- result2.fill(0); --> 为什么用 0 填充它?
请指教!
var isAnagram = function(s,t) {
if (s.length !== t.length)
result false;
const result1 = [];
result1.length = 26;
result1.fill(0);
const result2 = [];
result2.length = 26;
result2.fill(0);
for (let i = 0; i < s.length; i++) {
result1[s.charCodeAt(i) - 97]++;
result2[t.charCodeAt(i) - 97]++;
}
for (let i = 0; i < result1.length; i++) {
if (result1[i] !== result2[i]) {
return false;
}
}
return true;
};
++ 是自增运算符。它可以是前缀 (++i) 或 post-固定 (i++)。在这种情况下,它是 post-固定的:result1[s.charCodeAt(i) - 97]++
,因此它将增加 result1[s.charCodeAt(i) - 97]
.
26 只是字母表中的字母数(从 a 到 z)。
代码正在初始化这两个数组并fill
将它们设为 0,以便它可以将数组元素用作计数器。数组中的每个索引代表字母表中的一个字母,并存储该字母在字符串中出现的次数。
代码写得有点糟糕,让我们稍微改进一下,这样你的问题就自动消失了:
var isAnagram = function(string1, string2) {
if (string1.length !== string2.length)
return false; // here was a typo: result false
const alphabetLength = 26;
// returns an array of zeros (empty counters), each one per alphabet letter
const getAlphabetCounters = function() {
const counters = [];
counters.length = alphabetLength;
counters.fill(0);
return counters;
}
const countCharacter = function(c, counters) {
// zero for a, 25 for z
const position = c.charCodeAt(0) - 97;
counters[position]++;
}
const counters1 = getAlphabetCounters();
const counters2 = getAlphabetCounters();
for (let i = 0; i < string1.length; i++) {
countCharacter(string1[i], counters1);
countCharacter(string2[i], counters2);
}
for (let i = 0; i < counters1.length; i++) {
if (counters1[i] !== counters2[i]) {
return false;
}
}
return true;
};
但是使用这样的 "decremental" 方法可能是更好的主意:
var isAnagram = function(string1, string2) {
if (string1.length !== string2.length)
return false;
let letters1 = string1.split('');
let letters2 = string2.split('');
for (let letter of letters1) {
let position = letters2.indexOf(letter);
if(position == -1)
return false;
letters2.splice(position, 1);
}
return true;
};
或者如果一个人关心长字符串的性能,那么对其中的字母进行排序并直接比较是一种可行的方法。
这是我的解决方案版本。您甚至可以跳过末尾的 join(),因为您仍然可以比较两个数组。
const isAnagram = function(s, t) {
if (s.length !== t.length ) {
return false;
}
if (s.split('').sort().join('') === t.split('').sort().join('')) {
return true;
} else {
return false;
}
};
使用最少的数组函数和单个 for 循环
function anagram(str1, str2){
var isAnagram = true;
if(str1.length != str2.length){
isAnagram = false;
}else{
for(var i=0; i<str1.length;i++) {
if(!str2.includes(str1[i])){
isAnagram = false;
}
}
}
if(isAnagram){
console.log('string is anagram');
}else{
console.log('string is not anagram');
}
}
anagram('READ', 'DEAR');
var isAnagram = function(s, t) {
let sArr = s.split('');
let tArr = t.split('');
sArr.sort();
let newS = sArr.join('');
tArr.sort();
let newT = tArr.join('');
return newS === newT;
};
只需一行代码即可完成
const isAnagram = (s,t) => ( [...s].sort().join('') === [...t].sort().join(''))
console.log( isAnagram('anagram', 'nagaram') ) // true
console.log( isAnagram('anagram', 'xxx') ) // false
但是您的问题还要求管理所有 utf8 字符,我将其解释为必须消除 diacritic, for which there is an answer here.
我做了一些改动,只保留字母(不包括空格和其他标点符号),以便也能够处理几个单词的字谜:
const letters = str => str.toLowerCase().normalize("NFD").replace(/[^a-z]/g, '')
最终解决方案:
const letters = str => str.toLowerCase().normalize("NFD").replace(/[^a-z]/g, '')
, isAnagram = (s,t) => ( [...letters(s)].sort().join('') === [...letters(t)].sort().join(''))
;
const anagrams = // from wikipedia
[ { s: "evil"
, t: "vile" }
, { s: "New York Times"
, t: "monkeys write" }
, { s: "William Shakespeare"
, t: "I am a weakish speller" }
, { s: "Le commandant Cousteau"
, t: "Tout commença dans l'eau" } // with diacritic ( French )
, { s: "La crise économique"
, t: "Le scénario comique" }
, { s: "Question sans réponse"
, t: "Enquêtons sans espoir" }
, { s: "Chauve-souris"
, t: "Souche à virus" }
]
for (let {s,t} of anagrams )
console.log(`_${s}_, _${t}_ -> `, isAnagram(s,t))
.as-console-wrapper { max-height: 100% !important; top: 0; }