LintCode Kth Largest Element
原题链接在这里:http://www.lintcode.com/en/problem/kth-largest-element/#
在LeetCode上也有一道,采用了标准的quickSelect 方法,另外写了一篇帖子,代码更加模块化。
采用的quickSelect方法,取出pivot, 比pivot 小的都放在左边,比pivot大的都放在右边,若是pivot左边包括pivot的个数恰巧等于k, 就返回pivot.
若是大于k, 就在左边递归寻找第k小的数,若是大于k,就在右边递归寻找 第 (k-left)小的数。
题目中说要找第k 大的数,其实就是找 numbers.size()-k+1小的数。
pivot取的是最后一个数,跳出loop时l所在位置一定比pivot大,需要换回来,调换l和end上的数。
为了保证跳出loop时l上的数比pivot大,中间的 while 循环条件是 numbers.get(l) < pivot 就移动l,另一个while loop 条件却是 number.get(r) >= pivot 移动r, 这是为了防止陷入infinite loop.
AC Java:
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 findK(numbers.size()-k,numbers,0,numbers.size()-1); 7 } 8 private int findK(int k, ArrayList<Integer> numbers, int start, int end){ 9 if(start >= end){ 10 return numbers.get(start); 11 } 12 int m = partition(numbers, start, end); 13 if(m == k){ 14 return numbers.get(m); 15 }else if(m < k){ 16 return findK(k, numbers, m+1, end); 17 }else{ 18 return findK(k, numbers, start, m-1); 19 } 20 } 21 22 private int partition(ArrayList<Integer> numbers, int start, int end){ 23 int pivot = numbers.get(start); 24 int m = start; 25 int n = start + 1; 26 while(n<=end){ 27 if(numbers.get(n) < pivot){ 28 swap(numbers, ++m, n); 29 } 30 n++; 31 } 32 swap(numbers, start, m); 33 return m; 34 } 35 36 private void swap(ArrayList<Integer> numbers, int l, int r){ 37 int temp = numbers.get(l); 38 numbers.set(l,numbers.get(r)); 39 numbers.set(r,temp); 40 } 41 };
另外一种写法:
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 if(numbers == null || numbers.size() == 0 || k<1){ 7 return 0; 8 } 9 return getKth(numbers.size()-k+1, numbers, 0, numbers.size()-1); 10 } 11 12 private int getKth(int k, ArrayList<Integer> numbers, int start, int end){ 13 int pivot = numbers.get(end); 14 int l = start; 15 int r = end; 16 while(true){ 17 while(numbers.get(l) < pivot && l<r){ 18 l++; 19 } 20 while(numbers.get(r) >= pivot && r>l){ 21 r--; 22 } 23 if(l == r){ 24 break; 25 } 26 swap(numbers, l, r); 27 } 28 //l element is larger than pivot, swap it with pivot 29 swap(numbers, l, end); 30 if(k == l+1){ 31 return numbers.get(l); 32 }else if(k < l+1){ 33 return getKth(k, numbers, start, l-1); 34 }else{ 35 return getKth(k, numbers, l+1, end); 36 } 37 } 38 39 private void swap(ArrayList<Integer> numbers, int l, int r){ 40 int temp = numbers.get(l); 41 numbers.set(l,numbers.get(r)); 42 numbers.set(r,temp); 43 } 44 };