【问题标题】:Complexity of this implementation of countsort此计数排序实现的复杂性
【发布时间】:2022-01-10 20:37:40
【问题描述】:

下面的countsort实现的复杂度是多少?

void countSort(vector<int>& input)
{
    map<int, int> freq;
    for (int x: input) {
        freq[x]++;
    }
    int i = 0;
    for (auto p: freq)
    {
        while (p.second--) {
            input[i++] = p.first;
        }
    }
}

有人告诉我这是 O(n)。这不是for

for (int x: input) {
        freq[x]++;
    }

使其 O(n log n) 因为 C++ 中的 map 容器是平衡的 BST,而插入操作是 O(log n) ?

【问题讨论】:

  • 是的,不是一个很好的实现。

标签: c++ sorting dictionary


【解决方案1】:

Countsort 是一种线性 排序算法。通常线性排序算法有某种限制,允许它们是线性的,而不是完全通用的。

在这种情况下,限制是它对非负数(您可以将其扩展为 any 并仍然保持线性)整数进行排序,并使用值作为 中的键对它们进行计数频率数组

使用map 而不是数组会破坏目的。它使实现通用化,但不再是线性的。

【讨论】:

  • geeksforgeeks.org/implementing-counting-sort-using-map-in-c 这里说它是 O(n),这就是为什么我认为我错过了一些东西。
  • 红黑树的插入操作复杂度为 O(1),这就是他们这么说的原因。但在最坏的情况下,它是 O(log(n))
  • 那不还是 O(n) 吗?
  • 我在 cppreference 上添加了一个指向 map::insert 描述的链接。您可以看到在哪些情况下可以将其视为 O(1) 以及在哪些情况下不应该。代码在示例中的编写方式,按照规范,您应该假设 O(log(n)) 复杂度。
  • 另外,值得一提的是,countsort 在输入和输入范围上都是线性的 (O(n+k),其中 n 是输入的大小,k 是输入中 min 和 max 的差值)。所以它确实应该用于对值接近的整数数组进行排序,否则由于 k 的值很大,您的线性复杂度可能会超过一般算法的对数复杂度。
猜你喜欢
  • 2019-10-20
  • 2013-10-31
  • 1970-01-01
  • 2017-08-01
  • 2013-03-14
  • 1970-01-01
  • 2012-06-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多