JavaScript Anagram函数的时间复杂度

时间:2018-01-04 20:29:18

标签: javascript time-complexity computer-science anagram

我有一个赋值给一个函数,该函数将占用2个字符串并返回需要删除的字符数,以便使彼此的2个字符串字符串。我的问题是这个函数的时间复杂性是什么,以及是否有更快的方法来实现相同的结果。 这是我的解决方案:

function anagramDelete(str1, str2){
    let obj1 = {}, obj2 = {};

    // Load obj1 with all characters of str1 and their count
    str1.split('').forEach((char)=> {
        if(char in obj1){
            obj1[char]++;
        } else {
            obj1[char] = 1;
        }
    });

    // Load obj2 with all characters of str1 and their count
    str2.split('').forEach((char)=> {
        if(char in obj2){
            obj2[char]++;
        } else {
            obj2[char] = 1;
        }
    });

    // Track # of chars deleted
    let numOfDeletions = 0;

    // Compare each char in obj1 w obj2 and count deletions
    for(char in obj1){
        if(obj2[char]){
            numOfDeletions += Math.abs(obj2[char] - obj1[char]);
        } else {
            numOfDeletions += obj1[char];
        }
    }
    // Compare each char in obj2 w obj1 and count deletions
    for(char in obj2){
        if(!obj1[char]){
            numOfDeletions += obj2[char];
        }
    }
    return numOfDeletions;
}

据我所知,因为有4个循环,它将是O(4n)或只是O(n)。我这样说是因为没有嵌套循环。它是否正确?有更好的解决方案吗?

3 个答案:

答案 0 :(得分:1)

您可以使用单个对象并仅对绝对值求和。

此解决方案将字符串用作类似对象的数组。



function anagramDelete(str1, str2) {
    var letters = {};

    Array.prototype.forEach.call(str1, char => letters[char] = (letters[char] || 0) + 1);
    Array.prototype.forEach.call(str2, char => letters[char] = (letters[char] || 0) - 1);
 
    return Object.keys(letters).reduce((r, k) => r + Math.abs(letters[k]), 0);
}

console.log(anagramDelete('anagram', 'function'));




答案 1 :(得分:0)

不是更好,而是更短:

  function anagramDelete(str1, str2){
   const chars = {};
   var result = 0;

   for(const char of str1)
     chars[char] = (chars[char] || 0) +1;

   for(const char of str2)
     chars[char] = (chars[char] || 0) -1;

   for(const [char, count] of Object.entries(chars))
    result += Math.abs(count);

   return result;
 }

答案 2 :(得分:0)

您的代码为O(n + m);一般来说,人们并不太关心复杂性类中的常量。 n是第一个字符串的长度,m是第二个字符串的长度。

此外: 在您的情况下,确切地说,因为您提到O(4n) - 我不确定这是否准确。您可以使用split函数两次,这会将字符串转换为您的字符串中的字符数组。您没有在分析中考虑到这一点。

O(n + m)将是正确答案。

如果你想详细分析,那就是O(3n + 3m)。那是因为:
- 对于您使用splitO(n))的第一个字符串,您循环遍历每个字符(O(n))并再次循环以进行比较(O(n)
- 对于您使用splitO(m))的第二个字符串,您循环遍历每个字符(O(m))并再次循环以进行比较(O(m)

我认为你的代码是正确的。我没有检查过。

P.S .:
如果您对微调常数感兴趣,可以参考其他答案,它们可能比理论上的代码更快。在实践中,我认为这不重要。