Finding Nth item of unsorted list without sorting the list

前端 未结 9 2054
耶瑟儿~
耶瑟儿~ 2020-12-09 03:41

Hey. I have a very large array and I want to find the Nth largest value. Trivially I can sort the array and then take the Nth element but I\'m only interested in one element

相关标签:
9条回答
  • 2020-12-09 04:31

    You essentially want to produce a "top-N" list and select the one at the end of that list.

    So you can scan the array once and insert into an empty list when the largeArray item is greater than the last item of your top-N list, then drop the last item.

    After you finish scanning, pick the last item in your top-N list.

    An example for ints and N = 5:

    int[] top5 = new int[5]();
    top5[0] = top5[1] = top5[2] = top5[3] = top5[4] = 0x80000000; // or your min value
    
    for(int i = 0; i < largeArray.length; i++) {
        if(largeArray[i] > top5[4]) {
           // insert into top5:
           top5[4] = largeArray[i];
    
           // resort:
           quickSort(top5);
        }
    }
    
    0 讨论(0)
  • 2020-12-09 04:33

    Sorting would require O(nlogn) runtime at minimum - There are very efficient selection algorithms which can solve your problem in linear time.

    Partition-based selection (sometimes Quick select), which is based on the idea of quicksort (recursive partitioning), is a good solution (see link for pseudocode + Another example).

    0 讨论(0)
  • 2020-12-09 04:34

    As people have said, you can walk the list once keeping track of K largest values. If K is large this algorithm will be close to O(n2).

    However, you can store your Kth largest values as a binary tree and the operation becomes O(n log k).

    According to Wikipedia, this is the best selection algorithm:

     function findFirstK(list, left, right, k)
         if right > left
             select pivotIndex between left and right
             pivotNewIndex := partition(list, left, right, pivotIndex)
             if pivotNewIndex > k  // new condition
                 findFirstK(list, left, pivotNewIndex-1, k)
             if pivotNewIndex < k
                 findFirstK(list, pivotNewIndex+1, right, k)
    

    Its complexity is O(n)

    0 讨论(0)
提交回复
热议问题