c++ - 由于它们的大 O 复杂性,两个函数没有花费我预期的时间,谁能解释为什么?

标签 c++ algorithm time complexity-theory

所以我要解决的问题是找到一组整数中的多数元素,集合的大小 0 < n < 10^5,并且每个元素 0 < a < 10^9。所以我只需要找出哪个元素出现严格超过 n/2 次。

我有两个解决方案,我认为它们都是正确的,但它们的表现并不像我对它们的复杂性的理解所期望的那样。有人可以向我解释我做错了什么/误解了什么吗?

int getMajElement(vector<int> a)
{
std::unordered_map<int, int> countMap;
std::unordered_map<int, int>::iterator it;

for (int i : a)
{
    it = countMap.find(i);

    if (it == countMap.end())
    {
        countMap.insert(std::pair<int, int>(i, 1));
    }
    else
    {
        it->second++;
    }
}

int mostOfNum = 0;
int mostOfNumCount = 0;

for (std::pair<int, int>  pair : countMap)
{
    if (pair.second > mostOfNumCount)
    {
        mostOfNumCount = pair.second;
        mostOfNum = pair.first;
    }
}

if (mostOfNumCount > floor(a.size() / 2))
{
    return mostOfNum;
}
else
{
    return -1;
}
}

根据我的理解,第一个“for(int i : a)”应该在 O(n) 时间内运行,而查找/增加值应该在 hashmap 的 O(1) 时间内运行。第二个“for (std::pair pair : countMap)”循环也应该在 O(n) 时间内运行,因为我只是迭代最多 n 对。这总共需要 O(n) 时间。

此函数需要 2.4 秒才能运行 n = 10^5,并且每个 a = rand() % 10^9。我确保只为函数计时,而不是设置初始值。

然后下一个在相同条件下需要 0.70 秒,但我本以为第一个会更快。

第二个函数采用递归的分治法求解,需要O(n log(n))的时间。它基本上将列表分成 n 个单独的部分,然后检查左半部分的多数元素是否与右半部分的多数元素相同。如果不是,它将扫描列表以查看哪个值是该部分的总体多数 (value > floor((right - left)/2)) 并将其传回,否则 -1。

有人可以向我解释是什么导致了时差吗,这只是我犯的一个实现错误吗?

int get_majority_element(vector<int> &a, int left, int right) {

    if (left == right) return -1;
    if (left + 1 == right) return a[left];

    int mid = left + floor((right - left) / 2);

    int leftMajority = get_majority_element(a, left, mid);
    int rightMajority = get_majority_element(a, mid, right);

    if(leftMajority == rightMajority)
    {
        return leftMajority;
    }
    else if (rightMajority == -1)
    {
        return leftMajority;
    }
    else if (leftMajority == -1)
    {
        return rightMajority;
    }
    else
    {
        int leftCount = 0, rightCount = 0;
        for (int i = left; i < right; i++)
        {
            if (a[i] == leftMajority)
            {
                leftCount++;
            }
            else if (a[i] == rightMajority)
            {
                rightCount++;
            }
        }

        if (leftCount > floor((right - left) / 2))
        {
            return leftMajority;
        }
        else if (rightCount > floor((right - left) / 2))
        {
            return rightMajority;
        }
        else
        {
            return -1;
        }           
    }

    return -1;
}

最佳答案

评论太长了。

复杂性理论是关于随着数据量的增长单个算法会发生什么。它是 n --> 无穷大的极限。

在对相同大小的数据比较两种不同的算法时,它的用处要小得多。为什么?因为开销可以支配计算。例如,冒泡排序是 O(n^2)。但是在(非常)小的数据集上,它的性能可以胜过“更快”算法的合理实现。

正确的比较应该是每个算法在 10^5 个元素上的速度,然后是 10^6,然后是 10^7。也就是说,给定算法的速度如何增长。

关于c++ - 由于它们的大 O 复杂性,两个函数没有花费我预期的时间,谁能解释为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41198966/

相关文章:

c++ - 无法在 Linux 上构建 opencv_contrib 模块

c++ - 计算范围内的值时出现舍入误差

java - 等待服务器给出的答复给定的时间

mysql - 使用 MYSQL 为什么这会给我错误的时间戳?

c++ - 递归函数生成不包含两个相邻相同子串的字符串c++

c++ - 调试和自由执行中的信号处理

algorithm - 三角函数的范围缩减

javascript - 根据头的等级重新排序数组元素

c++ - 转换多个迭代器元素

python - Python 中的日出和日落时间