提问者:小点点

为什么vector比unordered_map快?


我正在解决LeetCode上的一个问题,但是还没有人能够解释我的问题。

给定一个任意的ransom note字符串和另一个包含来自所有杂志的字母的字符串,编写一个函数,如果可以从杂志构造ransom note,该函数将返回true;否则,它将返回false。

杂志串中的每个字母只能在你的赎金纸条中使用一次。

注意:您可以假设两个字符串都只包含小写字母。

canConstruct("a", "b") -> false
canConstruct("aa", "ab") -> false
canConstruct("aa", "aab") -> true
class Solution {
public:
    bool canConstruct(string ransomNote, string magazine) {
        if(ransomNote.size() > magazine.size()) return false;
        unordered_map<char, int> m;
        
        for(int i = 0; i < magazine.size(); i++)
            m[magazine[i]]++;
            
        for(int i = 0; i < ransomNote.size(); i++)
        {
            if(m[ransomNote[i]] <= 0) return false;
            m[ransomNote[i]]--;
        }
        return true;
    }
};
bool canConstruct(string ransomNote, string magazine) {
        int lettersLeft = ransomNote.size(); // Remaining # of letters to be found in magazine
        int arr[26] = {0};
        for (int j = 0; j < ransomNote.size(); j++) {
            arr[ransomNote[j] - 'a']++; // letter - 'a' gives a value of 0 - 25 for each lower case letter a-z
        }
        
        int i = 0;
        while (i < magazine.size() && lettersLeft > 0) {
            if (arr[magazine[i] - 'a'] > 0) {
                arr[magazine[i] - 'a']--;
                lettersLeft--;
            }
            i++;
        }
        if (lettersLeft == 0) {
            return true;
        } else {
            return false;
        }
    }

这两者都具有相同的复杂性,并且使用相同的结构来解决问题,但我不明白为什么其中一个所花费的时间几乎是另一个的两倍。查询向量的时间是O(1),但对于unordered_map也是如此。向其中一个添加入口/键也是同样的情况。

拜托,有人能解释一下为什么运行时间变化这么大吗?


共2个答案

匿名用户

首先要注意的是,虽然查询的平均时间是恒定的,但最坏的情况不是。正如您在这里看到的,它实际上上升到的量级,表示容器的大小。

其次,由于分配内存的顺序部分,因此对该内存的访问效率很高,而且实际上是恒定的,即使在最坏的情况下也是如此。(即简单的指针算术,而不是计算更复杂的散列函数的结果)还可能涉及到不同级别的顺序内存缓存(即取决于代码运行的平台),这可能会使使用的代码的执行比使用的代码的执行速度更快。

本质上,就复杂性而言,的最坏情况性能比的效率更高。更重要的是,大多数硬件系统提供了诸如缓存之类的特性,这使得的使用具有更大的优势。(即操作中较小的常数因子)

匿名用户

第二种方法使用纯C数组,其中对元素的访问是一个简单的指针解引用。但不是这种情况。有两点需要注意:

    实际上是一个哈希表,C++标准间接地要求使用开放寻址来实现它,这是一种比简单数组访问复杂得多的算法。/li>

由于这些原因,难怪数组版本会比工作得更好,即使它们具有相同的运行时复杂性。这是运行时复杂度相同的两个代码执行不同的另一个示例。

只有当您拥有大量的键时,您才会看到的好处(与此处的fixed 26相反)。