【问题标题】:What is the runtime complexity of std::map in C++?C++ 中 std::map 的运行时复杂度是多少?
【发布时间】:2020-10-13 01:19:30
【问题描述】:

我仍然对 C++ 中 std::map 的运行时复杂性感到有些困惑。我知道下面算法中的第一个 for 循环需要 O(N) 或线性运行时间。但是,第二个 for 循环有另一个 for 循环遍历地图。这是否会增加整体运行时的复杂性?换句话说,以下算法的整体运行时复杂度是多少?是 O(N) 还是 O(Nlog(N)) 还是别的什么?

    vector<int> smallerNumbersThanCurrent(vector<int>& nums) {
        
        vector<int> result;
        map<int, int> mp;
        
        for (int i = 0; i < nums.size(); i++) {
            mp[nums[i]]++;
        }
        
        for (int i = 0; i < nums.size(); i++) {
            int numElements = 0;
            for (auto it = mp.begin(); it != mp.end(); it++) {
                if (it->first < nums[i]) numElements += it->second;
            }
            result.push_back(numElements);
        }
        
        return result;
    }

【问题讨论】:

  • 取决于您对map 的操作。好的文档将提供其每种方法的时间复杂度。示例:en.cppreference.com/w/cpp/container/map/find#Complexity
  • 注意:第二个循环看起来过分了。就个人而言,我会返回 map,但如果您需要返回 vector,请与您的 Rubber Duck 讨论逻辑,看看是否有更简单的方法来获得您想要的东西..

标签: c++ arrays dictionary vector runtime


【解决方案1】:

map的复杂度是插入、删除、搜索等,但迭代总是线性的。

考虑到内部循环中的 n 次迭代(映射的大小)对于外循环(向量的大小,在您的代码中与地图的大小相同)。

【讨论】:

  • 地图的大小可能会更小。考虑相等元素的向量。
  • 对。没注意到。但即便如此,它也不会比 O(n^2) 更好。
  • 考虑 O(N*M) 其中 M 是 N 中唯一值的数量。
  • 你的回答肯定会解决我的困惑。谢谢!
【解决方案2】:

您的第二个 for 循环运行 nums.size() 次,所以我们称它为 N。看起来地图的条目与 nums 一样多,所以它包含相同的 N 个条目。那么大小为 N 的两个 for 循环是 N*N 或 N^2。

map 调用的 begin 和 end 函数是常数时间,因为据我所知,它们每个都有一个指针引用:

C++ map.end function documentation

请注意,如果您确实有两个 for 循环,但外部的一个大小为 N,而内部的一个大小不同,例如 M,那么复杂度是 M*N,而不是 N^2。在这一点上要小心,但是如果两个循环的 N 相同,则 N^2 是运行时。

【讨论】:

  • 看起来该地图的条目数与 nums 一样多 如果确实如此,那么mp[nums[i]]++; 将毫无意义。这段代码看起来是一个频率计数器。
最近更新 更多