Algorithm 按顺序查找k个最大元素

Algorithm 按顺序查找k个最大元素,algorithm,sorting,selection,Algorithm,Sorting,Selection,按顺序查找数组中k个最大元素(即从最大元素到第k个最大元素)的最快方法是什么 使用类似线性时间的中位数或内排序,找到第k个最大元素,并重新排列元素,使第k个元素前面的所有元素都大于第k个元素 使用快速排序算法(如heapsort或quicksort)从第k个元素开始对所有元素进行排序 步骤1需要时间,步骤2需要时间Ok log k。总的来说,该算法在+k log k上及时运行,速度非常非常快 希望这有帮助 @templatetypedef的解决方案可能是最快的,假设您可以修改或复制输入 < P>

按顺序查找数组中k个最大元素(即从最大元素到第k个最大元素)的最快方法是什么

使用类似线性时间的中位数或内排序,找到第k个最大元素,并重新排列元素,使第k个元素前面的所有元素都大于第k个元素

使用快速排序算法(如heapsort或quicksort)从第k个元素开始对所有元素进行排序

步骤1需要时间,步骤2需要时间Ok log k。总的来说,该算法在+k log k上及时运行,速度非常非常快


希望这有帮助

@templatetypedef的解决方案可能是最快的,假设您可以修改或复制输入


< P>可选的,可以使用C++中的堆或BST集在给定时刻存储k个最大元素,然后逐个读取数组元素。虽然这是在lg k上,但它不修改输入,只使用Ok附加内存。它也适用于从一开始就不知道所有数据的流。

C++还提供了部分排序算法,它解决了选择排序的最小k个元素的问题,时间复杂度为log k。没有提供选择最大k元素的算法,因为这应该通过反转排序谓词来完成

对于Perl,CPAN提供的模块Sort::Key::Top提供了一组函数,可以使用多个排序和自定义密钥提取过程从列表中选择前n个元素。此外,Statistics::CaseResampling模块提供了一个使用quickselect计算分位数的函数

Python自2.4版以来的标准库包括heapq.nsmalest和nlargest,返回排序列表,前者在On+k log n time中,后者在On log k time中。

基数排序解决方案:

使用基数排序,按降序对数组排序; 打印前K个元素。 时间复杂度:在*L上,其中L=最大元素的长度,可以假定L=O1。 使用的空间:启用以进行基数排序


但是,我认为基数排序的开销很高,这使得它的线性时间复杂性不那么吸引人。

1在 2使用Extract Max k times从Max Heap Oklogn中获取k个最大元素

时间复杂度:On+klogn

使用STL的C++实现如下:

#include <iostream>
#include<bits/stdc++.h>

using namespace std;

int main() {

  int arr[] = {4,3,7,12,23,1,8,5,9,2}; 

  //Lets extract 3 maximum elements
    int k = 3;  

    //First convert the array to a vector to use STL
    vector<int> vec;
    for(int i=0;i<10;i++){
        vec.push_back(arr[i]);
    }

  //Build heap in O(n)
  make_heap(vec.begin(), vec.end());

  //Extract max k times
  for(int i=0;i<k;i++){
      cout<<vec.front()<<" ";
      pop_heap(vec.begin(),vec.end());
      vec.pop_back();
  }
  return 0;
}
这是一个具有ON+k lgk复杂性的解决方案

int[] kLargest_Dremio(int[] A, int k) {
  int[] result = new int[k];
  shouldGetIndex = true;
  int q = AreIndicesValid(0, A.Length - 1) ? RandomizedSelet(0, A.Length-1,
    A.Length-k+1) : -1;
  Array.Copy(A, q, result, 0, k);
  Array.Sort(result, (a, b) => { return a>b; });
  return result;
} 
AreIndicates Valid和RandomizedSelet在中定义。

有一个关于性能和受限资源的问题

为前3个值创建一个值类。使用这样的累加器来减少平行流。根据上下文内存、电源限制并行性

class BronzeSilverGold {
    int[] values = new int[] {Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE};

    // For reduction
    void add(int x) {
        ...
    }

     // For combining two results of two threads.
    void merge(BronzeSilverGold other) {
        ...
    }
}
在您的星座中必须限制并行性,因此请在以下位置指定N_线程:

try {
    ForkJoinPool threadPool = new ForkJoinPool(N_THREADS);
    threadPool.submit(() -> {
        BronzeSilverGold result = IntStream.of(...).parallel().collect(
            BronzeSilverGold::new,
            (bsg, n) -> BronzeSilverGold::add,
            (bsg1, bsg2) -> bsg1.merge(bsg2));
        ...
    });
} catch (InterruptedException | ExecutionException e) {
    prrtl();
}

非常好的方法。也许您想补充几句关于存在重复项的情况,特别是kth最大的关系。不是游戏改变者,而是要考虑的东西。“辛苦,实际上它对算法没有任何区别。”RICI:当第1步措辞时,如果K-1元素大于KTH元素,那么你就不会成功。如果这些单词被替换为大于或等于第k个元素,它也不能精确地解决问题。我是不是太挑剔了?是的,但是…@hardmath-如果可能存在重复,那么我们可以在预期的时间内通过将所有元素放入哈希表并将唯一元素读回数组来解决这个问题。然后您可以使用相同的算法。@hardmath:如果数组的元素少于k个,如果您想非常挑剔的话,它肯定不起作用。否则,我建议查找k个最大元素之间的差异对于查找大于或等于所有剩余元素的k个元素来说是合理的,特别是考虑到精确算法的链接。您能假设数组没有重复元素吗?还是你必须解释这个案子?我们必须解释这个案子