LintCode-Kth Largest Element

Find K-th largest element in an array.

Note

You can swap elements in the array

Example

In array [9,3,2,4,8], the 3th largest element is 4

Challenge

O(n) time, O(1) space

Analysis:

We use Quick partition to perform the selection. We use the method of "median of medians", i.e., median of every group of 5 elements, to select the pivot. In this way, we can guarantee that the complexity in the worst case is still O(n).

Reference:

http://blog.csdn.net/v_JULY_v/article/details/6370650

http://blog.csdn.net/v_july_v/article/details/6431001

Solution:

 1 class Solution {
 2     //param k : description of k
 3     //param numbers : array of numbers
 4     //return: description of return
 5     public int kthLargestElement(int k, ArrayList<Integer> numbers) {
 6         return selectK(numbers,0,numbers.size()-1,k);
 7     }
 8 
 9     public void insertSort(ArrayList<Integer> numbers, int start, int end){
10         for (int i=start;i<=end;i++){
11             int key = numbers.get(i);
12             int ind = i-1;
13             while (ind>=start && numbers.get(ind)<key){
14                 numbers.set(ind+1,numbers.get(ind));
15                 ind--;
16             }
17             numbers.set(ind+1,key);
18         }
19     }        
20 
21     public void swap(ArrayList<Integer> numbers, int x, int y){
22         int temp = numbers.get(x);
23         numbers.set(x,numbers.get(y));
24         numbers.set(y,temp);
25     }
26 
27     //This function selects the kth largest number in the range numbers[start...end].
28     //For example, if start=8, end=11, k=2, we will select the 2nd largest number in the range numbers[8...11].
29     //So in the code, we need be very carefull about the index of the kth largest number.
30     public int selectK(ArrayList<Integer> numbers, int start, int end, int k){
31         if (end-start+1<=5){
32             insertSort(numbers,start,end);
33             return numbers.get(start+k-1);
34         }
35 
36         //Get the median of every group of 5 elements.
37         int pos = start;
38         int cur = start;
39         while (true){
40             int curEnd = Math.min(cur+4,end);
41             //For even number, we pick up the later median, that is why there is plus one at last.
42             int median5 = selectK(numbers,cur,curEnd,(curEnd-cur+1)/2+1);
43             swap(numbers,pos,(curEnd+cur+1)/2);
44             pos++;
45             if (curEnd==end) break;
46             else cur = curEnd+1;
47         }
48 
49         //Get the median of median5s, i.e., median of [start...pos-1].
50         int median = selectK(numbers,start,pos-1,(pos-start)/2+1);
51         int mInd = start;
52         for (int i=start;i<=start+4;i++) 
53             if (numbers.get(i)==median){
54                 mInd = i;
55                 break;
56             }
57 
58         
59         //Use the median as the pivot to partition [start...end].
60         swap(numbers,mInd,end);
61         int p1 = start, p2 = end-1;
62         while (p1<end && numbers.get(p1)>median) p1++;
63         while (p2>0 && numbers.get(p2)<median) p2--;
64         while (p1<p2){
65             swap(numbers,p1,p2);
66             p1++;
67             p2--;
68             while (p1<end && numbers.get(p1)>median) p1++;
69             while (p2>0 && numbers.get(p2)<median) p2--;
70         }
71         swap(numbers,p1,end);
72         if (p1-start+1==k)
73             return numbers.get(p1);
74         else if (p1-start+1>k)
75             return selectK(numbers,start,p1-1,k);
76         else 
77             return selectK(numbers,p1+1,end,k-(p1-start+1));
78     }
79             
80         
81             
82 };

 

posted @ 2014-12-29 04:16  LiBlog  阅读(348)  评论(0编辑  收藏  举报