C++ 第k大数

C++ 第k大数,c++,data-structures,C++,Data Structures,我可以使用什么样的数据结构来解决此问题: 如果输入包含: +1-插入值为Ki的元素 0-查找并打印第k个最大元素 -1-删除值为Ki的元素 输入示例: 8 +1 5 +1 3 +1 7 0 2 -1 3 0 1 +1 10 0 3 和输出: 5 7 5 数据结构:自平衡BST(如红黑树) c++中的容器:set 时间复杂性: 插入:O(log(n)) 删除:O(日志(n)) 第K阶统计量:O(n) 我会使用某种形式的二进制搜索树: std::set通过键访问,看起来非常适合您的需要。

我可以使用什么样的数据结构来解决此问题:

如果输入包含:

  • +1-插入值为Ki的元素
  • 0-查找并打印第k个最大元素
  • -1-删除值为Ki的元素
输入示例:

8
+1 5
+1 3
+1 7
0 2
-1 3
0 1
+1 10
0 3
和输出:

5
7
5
数据结构:自平衡BST(如红黑树)

c++中的容器:set

时间复杂性:

  • 插入:
    O(log(n))
  • 删除:
    O(日志(n))
  • 第K阶统计量:
    O(n)

我会使用某种形式的二进制搜索树:
std::set
通过键访问,看起来非常适合您的需要。
std::map
是一个关联容器,通常实现为红黑树

在你的情况下,我会选择
std::set

//getting the n-th element in set
auto it = std::next(myset.begin(), n);

为了完整起见,我还应该提到std::vector+std::sort,它在算法上效率较低,但如果没有大型数据集,由于数据局部性(vector以顺序方式在预先分配的内存块中放置包含的对象),它的性能会更高。

a?老实说,您可以使用任何容器。哪个容器是最好的有待讨论。一个保持排序的容器。添加/删除元素始终保持排序顺序(从大到小)。查找第K个最大值变得很简单:在索引K处访问元素。
std::set
可能是最简单的。从大到小排序。我不认为性能是这里真正的问题,所以请放心。通常来说,在自平衡BST中,没有理由认为第K个元素需要那么慢<代码>标准::设置使它变得如此缓慢、真实,但…@Yakk同意。在普通RBT中,您找不到比
O(n)
更快的第K个元素,因为您必须遍历树。如果BST稍微修改了一点;就像为每个节点在左子树和右子树中添加节点计数器一样,它可以是
O(log(n))
std::set
不通过索引访问。它是通过密钥访问的。这并不重要,你可以在O(K)时间内迭代它,所以..在键入集合块时考虑了蛮力向量+排序解决方案:)修复了它。事实上,我认为向量解决方案在很多用例中都更好。数据局部性在每周的每一天都会战胜算法复杂性的微小增加。星期天两次。
std::set
不太合适。除了
std::set
的拟合不精确之外,没有理由为查找第k个键花费O(n)成本。一个简单的跳过列表将支持O(lg n)预期时间内的每一个操作,例如,每个节点上都有计数的BST也是如此<代码>标准两者都缺少。