【问题标题】:Fast anagrams checker algorithm (HackerRank)快速字谜检查算法 (HackerRank)
【发布时间】:2021-04-21 15:22:09
【问题描述】:

问题:

给定两个字符串数组,对于列表(查询)中的每个字符串,确定它在另一个列表(字典)中有多少个字谜。 它应该返回一个整数数组。

例子:

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;
}

但是,对于较长的测试用例,它会返回超时错误。需要一些帮助来优化它。有什么建议?我正在尝试在 JavaScript 中实现它。

【问题讨论】:

  • .sort() 很贵,尽量避免
  • 谢谢叶夫根。如果两个字符串是字谜,还有其他方法可以比较吗?
  • 顺便说一句,这个问题已经回答了stackoverflow.com/questions/64685582/…

标签: javascript algorithm anagram


【解决方案1】:

您可能希望避免使用(昂贵的)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)

【讨论】:

    【解决方案2】:

    稍微冗长的方法 - 但它对我来说有效并且有意义 - 对于原始数组中的每个单词,找到目标数组中长度相同的单词,然后计算那些是原始单词的单词单词(字谜是由相同字母按任意顺序组成的另一个单词)。

    所以步骤是-

    遍历 firat 数组并针对每个单词 - 过滤目标数组以获取与该单词长度相同的所有单词 (potentialAnagrams)

    然后遍历潜在的Anagrams数组并将每个单词传递给一个函数,该函数检查是否存在所有字母以及原始单词中的唯一字母(在给定的示例中 - 这将是 [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];

    【讨论】:

    • console.log(isAnagram('ab', 'bab')) // true
    • @YevgenGorbunkov - 因为单词长度比较发生在过滤器函数中,然后单词被传递给 isAnagram() - 唯一通过的单词实际上长度相等 - 所以“ab”和“bab” " 永远不会被传递给函数——但这就是说——我同意你的观点,所以在函数中添加了长度检查和提前返回,以确保 "ab" 和 "bab" 不被认为是有效的。如果这是非 SO 环境中的真实代码,我确信应该包括其他测试或检查示例。感谢您的反馈:)
    • 我想,你明白了:检查两个单词中是否存在所有相同的字母是不够的,但这些字母的数量应该相同。因此,'aab''bba' 不会被视为彼此的字谜。注意,现在字符串长度是一样的。
    • 此外,为不同大小的字符串返回消息是一个糟糕的设计选择,因为现在您的函数可能会在预期false 时返回真值,所以如果与.filter() 一起使用,例如,可能会给出不正确的输出。
    • 顺便说一句,如果您缺少 mocha 以确保您的解决方案正确涵盖所有测试场景,您可以轻松部署一个(考虑 the example)。
    猜你喜欢
    • 2013-02-28
    • 2011-11-03
    • 2017-12-27
    • 1970-01-01
    • 2010-12-01
    • 2012-11-03
    • 2019-02-02
    • 2011-01-17
    • 1970-01-01
    相关资源
    最近更新 更多