Lintcode: Kth Largest Element 解题报告

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

原题链接:

http://www.lintcode.com/en/problem/kth-largest-element/

SOLUTION 1:

使用改进的Quicksort partition,可以达到O(n)的时间复杂度,并且不需要额外空间。

请参考: http://en.wikipedia.org/wiki/Quickselect#Time_complexity

 

时间复杂度:如果我们是这样的数组:1,2,3,4,5,然后又每一次取左边的当pivot,就会达到最坏的时间复杂度。也就是O(N2)

我们也有一些解决方法:

以下来自维基,我们可以取3个数进行平均。

http://stackoverflow.com/questions/7559608/median-of-three-values-strategy

The easiest solution is to choose a random pivot, which yields almost certain linear time. Deterministically, one can use median-of-3 pivot strategy (as in the quicksort), which yields linear performance on partially sorted data, as is common in the real world. However, contrived sequences can still cause worst-case complexity; David Musser describes a "median-of-3 killer" sequence that allows an attack against that strategy, which was one motivation for his introselect algorithm.

 1 package Algorithms.algorithm.NChapter.findKthNumber;
 2 
 3 import java.util.ArrayList;
 4 
 5 // The link: 
 6 
 7 // http://www.lintcode.com/en/problem/kth-largest-element/
 8 
 9 class KthLargestElement_lintCode {
10     //param k : description of k
11     //param numbers : array of numbers
12     //return: description of return
13     public int kthLargestElement(int k, ArrayList<Integer> numbers) {
14         // write your code here
15         if (k < 1 || numbers == null) {
16             return 0;
17         }
18         
19         return getKth(numbers.size() - k + 1, numbers, 0, numbers.size() - 1);
20     }
21     
22     public int getKth(int k, ArrayList<Integer> numbers, int start, int end) {
23         // Choose the last one as the pivot
24         int pivot = numbers.get(end);
25         
26         int left = start;
27         int right = end;
28         
29         while (true) {
30             while (numbers.get(left) < pivot && left < right) {
31                 left++;    
32             }
33             
34             while (numbers.get(right) >= pivot && right > left) {
35                 right--;
36             }
37             
38             if (left == right) {
39                 break;
40             }
41             
42             swap(numbers, left, right);
43         }
44         
45         // left: the first one which is bigger than pivot.
46         swap(numbers, left, end);
47         
48         if (k == left + 1) {
49             return pivot;
50         // Try to find the element from the left side.
51         } else if (k < left + 1) {
52             return getKth(k, numbers, start, left - 1);
53         } else {
54         // Try to find the element from the right side.            
55             return getKth(k, numbers, left + 1, end);
56         }
57     }
58     
59     /*
60         Swap the two nodes.
61     */
62     public void swap(ArrayList<Integer> numbers, int n1, int n2) {
63         int tmp = numbers.get(n1);
64         numbers.set(n1, numbers.get(n2));
65         numbers.set(n2, tmp);
66     }
67 };
View Code

 

SOLUTION 2:

以下这些链接有详细的讨论,就不再一一叙述了。目前来讲Solution 1应该是最优的啦。

http://www.geeksforgeeks.org/k-largestor-smallest-elements-in-an-array/

http://www.quora.com/What-is-the-most-efficient-algorithm-to-find-the-kth-smallest-element-in-an-array-having-n-elements

 

GITHUB:

https://github.com/yuzhangcmu/LeetCode_algorithm/blob/master/algorithm/NChapter/findKthNumber/KthLargestElement_lintCode.java

posted on 2014-12-15 14:30  Yu's Garden  阅读(6997)  评论(0编辑  收藏  举报

导航