Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/164.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 选择两个向量中的n个最大元素_C++ - Fatal编程技术网

C++ 选择两个向量中的n个最大元素

C++ 选择两个向量中的n个最大元素,c++,C++,我有两个向量,每个向量包含n个未排序的元素,如何在这两个向量中得到n个最大的元素 我的解决方案是将两个向量合并成一个包含2n个元素的向量,然后使用std::nth_元素算法,但我发现这不是很有效,所以任何人都有更有效的解决方案。非常感谢。您可以将元素推入优先级队列,然后弹出n元素。假设n远小于n,这是非常有效的。如果n=minElem或L的大小小于n,则获取minElem是便宜的,并且在L中插入排序比两个向量的排序便宜) { 将元素添加到L 如果(L>n的大小) { 从L中删除最小的元素 } }

我有两个向量,每个向量包含n个未排序的元素,如何在这两个向量中得到n个最大的元素


我的解决方案是将两个向量合并成一个包含2n个元素的向量,然后使用
std::nth_元素
算法,但我发现这不是很有效,所以任何人都有更有效的解决方案。非常感谢。

您可以将元素推入
优先级队列
,然后弹出
n
元素。

假设n远小于n,这是非常有效的。如果n=minElem或L的大小小于n,则获取minElem是便宜的,并且在L中插入排序比两个向量的排序便宜) { 将元素添加到L 如果(L>n的大小) { 从L中删除最小的元素 } } }
向量堆;
堆保留(n+1);
向量::迭代器left=leftVec.begin(),right=righvec.begin();
对于(int i=0;i
注意:我直接使用*\u堆而不是优先级队列,因为优先级队列不提供对其底层数据结构的访问。这是O(N logn),比朴素的O(N logn)方法稍微好一点,如果N你可以很容易地在两个向量上并行执行“N元素”算法(至少是在平均情况下仅线性的简单变量)

  • 选择一个支点
  • 分区(std::Partition)通过该轴分配两个向量。第一个向量由秩为i的元素划分,第二个向量由秩为j的元素划分。我在这里按降序排列
  • 如果i+jn,则在左侧递归n个最大元素。如果你点击i+j==n,停止递归
  • 基本上,您只需要确保在每一步中都使用相同的轴来划分两个向量。如果选择了一个合适的枢轴,该算法在一般情况下是线性的(并且可以正常工作)

    另见:


    编辑:(希望)稍微澄清了算法。

    您想要n个元素还是单个第n个元素?n接近n还是与n相比非常小?但这有n*log(n)复杂度。这个问题可以在O(N)中解决。如果您懒惰,您可以编写一个简单的迭代器包装器“虚拟地”连接数组,并继续使用std::nth_元素。不过,重新实现两个阵列的算法可能更快。您能提供更多的信息吗?关于迭代器包装器。您编写了一个类,该类的行为类似于对向量的迭代器,对于前n个索引,它对第一个向量中的元素取消引用,对于下n个索引,它对第二个向量中的元素取消引用。
    L := SortedList()
    For Each element in any of the vectors do
    {
      minElem := smallest element in L
      if( element >= minElem or if size of L < n)
      {
        add element to L
        if( size of L > n )
        {
          remove smallest element from L
        }
      }
    }
    
    vector<T> heap;
    heap.reserve(n + 1);
    
    vector<T>::iterator left = leftVec.begin(), right = rightVec.begin();
    
    for (int i = 0; i < n; i++) {
        if (left != leftVec.end()) heap.push_back(*left++);
        else if (right != rightVec.end()) heap.push_back(*right++);
    }
    
    if (left == leftVec.end() && right == rightVec.end()) return heap;
    
    make_heap(heap.begin(), heap.end(), greater<T>());
    
    while (left != leftVec.end()) {
        heap.push_back(*left++);
        push_heap(heap.begin(), heap.end(), greater<T>());
        pop_heap(heap.begin(), heap.end(), greater<T>());
        heap.pop_back();
    }
    
    /* ... repeat for right ... */
    
    return heap;