Find the kth largest element in an unsorted array.
For example,
Given [3,2,1,5,6,4]
and k = 2, return 5.
Note:
You may assume k is always valid, 1 ≤ k ≤ array's length.
这个题目有个直观的解法,就是先排序(从大到小),然后在取第K个数字就可以了,用(java,c++,c的)排序算法可以在O(nlogn)时间里完成;
但是其实并不需要全排序,从里面选定一个数字,简称x,把比x大的数字放到数组S中,如果S的size为k - 1, 那么x就是第k大得数字;如果S的size比k - 1大,那么只要在S中找第k大得数字;如果S的size比k - 1小,那么就可以从减去S的x的数组中,找k - 1 - size(S)的数字即可;
public class Solution {
public static int qsort(int[] nums, int left, int right, int k) {
if (left + 3 <= right) {
int pivot = median3(nums, left, right);
// int pivot = nums[right];
int i = left, j = right - 1;
while (i < j) {
while (nums[++i] > pivot) {
}
while (nums[--j] < pivot) {
}
if (i < j) {
swap(nums, i, j);
}
}
swap(nums, i, right - 1);
if (k == i) {
return nums[i];
} else if (k > i) {
return qsort(nums, i + 1, right, k);
} else {
return qsort(nums, left, i - 1, k);
}
} else {
insertSort(nums, left, right);
return nums[k];
}
}
private static int median3(int[] nums, int left, int right) {
int center = (left + right) / 2;
if (nums[left] < nums[center]) {
swap(nums, left, center);
}
if (nums[left] < nums[right]) {
swap(nums, left, right);
}
if (nums[center] < nums[right]) {
swap(nums, center, right);
}
swap(nums, center, right - 1);
return nums[right - 1];
}
private static void insertSort(int[] nums, int left, int right) {
for (int i = left + 1; i <= right; i++) {
int tmp = nums[i];
int j = i;
while (j > 0 && nums[j - 1] < tmp) {
nums[j] = nums[j - 1];
j -= 1;
}
nums[j] = tmp;
}
}
private static void swap(int[] nums, int i, int j) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
public static int findKthLargest(int[] nums, int k) {
if (nums.length == 1) {
return nums[0];
}
return qsort(nums, 0, nums.length - 1, k - 1);
}
public static void main(String[] args) {
int[] nums = {3, 3, 3, 3, 3, 3, 3, 3, 3};
System.out.println(findKthLargest(nums, 8));
}
}
现在一般也不会自己编写quick sort和insert sort,会直接调用Arrays.sort,所以为了写这段代码还把《Data Structures and Algorithm Analysis in C》翻出来参考。
以下是scala的实现,就比较straight foward了,
object App extends App {
def qsort(list: List[Int], k: Int): Int =
list match {
case Nil => throw new Exception("should not get here")
case h :: tail =>
val (left, right) = tail.partition(_ > h)
if (left.size == k - 1) {
h
} else if (left.size > k - 1) {
qsort(left, k)
} else {
qsort(right, k - left.size - 1)
}
}
def findKthLargest(nums: Array[Int], k: Int) = qsort(nums.toList, k)
println(findKthLargest(Array(3, 3, 3, 3, 3, 3, 3, 3, 3), 8))
println(findKthLargest(Array(3, 2, 1, 5, 6, 4), 2))
}
但大概不会java那么高效,但表现力应该要强很多;