快速字谜检查算法 (HackerRank)
Fast anagrams checker algorithm (HackerRank)
问题:
给定两个字符串数组,对于列表(查询)中的每个字符串,确定它在另一个列表(字典)中有多少个字谜。
它应该 return 一个整数数组。
示例:
query = ["a", "nark", "bs", "hack", "stair"]
dictionary = ['hack', 'a', 'rank', 'khac', 'ackh', 'kran', 'rankhacker', 'a', 'ab', 'ba', 'stairs', 'raits']
答案是 [2, 2, 0, 3, 1]
,因为 query[0]
('a') 在 dictionary
中有 2 个字谜:'a' 和 'a' 等等在...
这是我想出的代码:
function sortArray(array) {
let answer = [];
for(let i = 0; i< array.length ; i++) {
let data = array[i].split('').sort().join('');
answer.push(data);
}
return answer;
}
function stringAnagram(dictionary, query) {
// Write your code here
let sortedDict = sortArray(dictionary);
let sortedQuery = sortArray(query);
let answer = [];
console.log(sortedDict.length);
console.log(sortedQuery.length);
sortedQuery.map(data => {
let i = 0;
sortedDict.forEach(dictData => {
if(data === dictData)
i++;
})
answer.push(i);
})
return answer;
}
然而,对于较长的测试用例,它是 returning 超时错误。需要一些帮助来优化它。有什么建议么?我正在努力在 JavaScript.
中实现它
您可能希望避免使用(昂贵的)Array.prototype.sort()
来检测变位词,并为您的变位词检测算法提供尽可能多的快捷方式。
因此,如果假设变位词应该是具有相同字符数的相同长度的字符串,您可以这样做:
const query = ["a", "nark", "bs", "hack", "stair"],
dictionary = ['hack', 'a', 'rank', 'khac', 'ackh', 'kran', 'rankhacker', 'a', 'ab', 'ba', 'stairs', 'raits'],
charCount = s => [...s].reduce((acc,c) =>
(acc[c]=(acc[c]||0)+1, acc), {}),
areAnagrams = (s1, s2) => {
if(s1.length != s2.length) return false
const s1CharCount = charCount(s1),
s2CharCount = charCount(s2),
result = Object
.keys(s1CharCount)
.every(char =>
s2CharCount[char] == s1CharCount[char])
return result
},
outcome = query.map(word =>
dictionary
.filter(_word => areAnagrams(word, _word))
.length
)
console.log(outcome)
稍微更冗长的方法 - 但它有效并且对我有意义 - 对于原始数组中的每个单词,找到目标数组中长度相同的单词,然后计算那些是原始单词(变位词是由相同字母以任意顺序组成的另一个单词)。
所以步骤是-
迭代 firat 数组并针对每个单词 - 过滤目标数组以获得与该单词长度相同的所有单词(potentialAnagrams)
然后遍历 potentialAnagrams 数组并将每个单词传递给一个函数,该函数检查是否存在所有字母并且仅存在原始单词中的字母(在给定的示例中 - 即 [2, 2, 0, 3, 1]
将单词的所有字谜相加,并将计数传递给记录为最终结果的数组。
const queryArr = ["a", "nark", "bs", "hack", "stair"];
const dictionaryArr = ['hack', 'a', 'rank', 'khac', 'ackh', 'kran', 'rankhacker', 'a', 'ab', 'ba', 'stairs', 'raits'];
let anagramsArr = [];
queryArr.forEach(function(query){
let anagramsCount = 0
const potentialAnagrams = dictionaryArr.filter(el => el.length === query.length);
potentialAnagrams.forEach(function(potentialAnagram){
if(isAnagram(query,potentialAnagram)){
anagramsCount++
}
})
anagramsArr.push(anagramsCount);
})
function isAnagram(word1, word2){
let count = 0;
const word1Arr = word1.split('');
const word2Arr = word2.split('');
if( word1Arr.length !== word2Arr.length) {
return 'Invalid data - words 1 and 2 are of different lengths';
}
word1Arr.forEach(function(letter){
if(word2.indexOf(letter) !== -1) {
count++
}
})
return count === word1Arr.length
}
console.log(isAnagram('ab', 'bab')); //gives 'Invalid data - words 1 and 2 are of different lengths';
console.log(anagramsArr); //gives [2, 2, 0, 3,1];
问题:
给定两个字符串数组,对于列表(查询)中的每个字符串,确定它在另一个列表(字典)中有多少个字谜。 它应该 return 一个整数数组。
示例:
query = ["a", "nark", "bs", "hack", "stair"]
dictionary = ['hack', 'a', 'rank', 'khac', 'ackh', 'kran', 'rankhacker', 'a', 'ab', 'ba', 'stairs', 'raits']
答案是 [2, 2, 0, 3, 1]
,因为 query[0]
('a') 在 dictionary
中有 2 个字谜:'a' 和 'a' 等等在...
这是我想出的代码:
function sortArray(array) {
let answer = [];
for(let i = 0; i< array.length ; i++) {
let data = array[i].split('').sort().join('');
answer.push(data);
}
return answer;
}
function stringAnagram(dictionary, query) {
// Write your code here
let sortedDict = sortArray(dictionary);
let sortedQuery = sortArray(query);
let answer = [];
console.log(sortedDict.length);
console.log(sortedQuery.length);
sortedQuery.map(data => {
let i = 0;
sortedDict.forEach(dictData => {
if(data === dictData)
i++;
})
answer.push(i);
})
return answer;
}
然而,对于较长的测试用例,它是 returning 超时错误。需要一些帮助来优化它。有什么建议么?我正在努力在 JavaScript.
中实现它您可能希望避免使用(昂贵的)Array.prototype.sort()
来检测变位词,并为您的变位词检测算法提供尽可能多的快捷方式。
因此,如果假设变位词应该是具有相同字符数的相同长度的字符串,您可以这样做:
const query = ["a", "nark", "bs", "hack", "stair"],
dictionary = ['hack', 'a', 'rank', 'khac', 'ackh', 'kran', 'rankhacker', 'a', 'ab', 'ba', 'stairs', 'raits'],
charCount = s => [...s].reduce((acc,c) =>
(acc[c]=(acc[c]||0)+1, acc), {}),
areAnagrams = (s1, s2) => {
if(s1.length != s2.length) return false
const s1CharCount = charCount(s1),
s2CharCount = charCount(s2),
result = Object
.keys(s1CharCount)
.every(char =>
s2CharCount[char] == s1CharCount[char])
return result
},
outcome = query.map(word =>
dictionary
.filter(_word => areAnagrams(word, _word))
.length
)
console.log(outcome)
稍微更冗长的方法 - 但它有效并且对我有意义 - 对于原始数组中的每个单词,找到目标数组中长度相同的单词,然后计算那些是原始单词(变位词是由相同字母以任意顺序组成的另一个单词)。
所以步骤是-
迭代 firat 数组并针对每个单词 - 过滤目标数组以获得与该单词长度相同的所有单词(potentialAnagrams)
然后遍历 potentialAnagrams 数组并将每个单词传递给一个函数,该函数检查是否存在所有字母并且仅存在原始单词中的字母(在给定的示例中 - 即 [2, 2, 0, 3, 1]
将单词的所有字谜相加,并将计数传递给记录为最终结果的数组。
const queryArr = ["a", "nark", "bs", "hack", "stair"];
const dictionaryArr = ['hack', 'a', 'rank', 'khac', 'ackh', 'kran', 'rankhacker', 'a', 'ab', 'ba', 'stairs', 'raits'];
let anagramsArr = [];
queryArr.forEach(function(query){
let anagramsCount = 0
const potentialAnagrams = dictionaryArr.filter(el => el.length === query.length);
potentialAnagrams.forEach(function(potentialAnagram){
if(isAnagram(query,potentialAnagram)){
anagramsCount++
}
})
anagramsArr.push(anagramsCount);
})
function isAnagram(word1, word2){
let count = 0;
const word1Arr = word1.split('');
const word2Arr = word2.split('');
if( word1Arr.length !== word2Arr.length) {
return 'Invalid data - words 1 and 2 are of different lengths';
}
word1Arr.forEach(function(letter){
if(word2.indexOf(letter) !== -1) {
count++
}
})
return count === word1Arr.length
}
console.log(isAnagram('ab', 'bab')); //gives 'Invalid data - words 1 and 2 are of different lengths';
console.log(anagramsArr); //gives [2, 2, 0, 3,1];