Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.
Example 1:
Input: [3,2,1,5,6,4]
and k = 2
Output: 5
Example 2:
Input: [3,2,3,1,2,4,5,5,6]
and k = 4
Output: 4
Note:
You may assume k is always valid, 1 ≤ k ≤ array's length.
这题是一道很好的面试题目,
题目短小,很快就能说清题意
有很多种解法。从简单到复杂的解法都有,梯度均匀。 不需要预先知道特殊领域知识。
这题有很多思路:
1. 按从大到小全排序,然后取第 k 个元素,时间复杂度 O(nlogn) ,空间复杂度 O(1)
2. 利用堆进行部分排序。维护一个大根堆,将数组元素全部压入堆,然后弹 出 k 次,第 k 个就是答案。时间复杂度 O(klogn) ,空间复杂度 O(n)
3. 选择排序,第 k 次选择后即可得到第 k 大的数,时间复杂度 O(nk) ,空间复杂度 O(1)
4. 堆排序,维护一个 k 大小的小根堆,将数组中的每个元素与堆顶元素进行比较,如果比堆顶元素大,则删除堆顶元素并添加该元素,如果比堆顶元素小, 则什么也不做,继续下一个元素。时间复杂度 O(nlogk) ,空间复杂
度 O(k) 。
5. 利用快速排序中的partition思想,从数组中随机选择一个元素x,把数组划分为 前后两部分 sa 和 sb , sa 中的元素小于x, sb 中的元素大于或等于x。这时有两种情况:
i. sa 的元素个数小于 k ,则递归求解 sb 中的第 k-|sa| 大的元素
ii. sa 的元素个数大于或等于 k ,则递归求解 sa 中的第 k 大的元素
时间复杂度 O(n) ,空间复杂度 O(1)
思路4和5比较高效,可以接受,其他思路太慢了,不采纳。
思路4:
class Solution {
public int findKthLargest(int[] nums, int k) {
Queue<Integer> q = new PriorityQueue();
for (int i : nums) {
if (q.size() < k) {
q.offer(i);
} else if (q.peek() < i) {
q.poll();
q.offer(i);
}
}
return q.peek();
}
}
思路5:
/**
*
* @author dongb
* Kth Largest Element in an Array
* Use partition and quick sort, then random
* TC O(n). SC O(1)
*
*/
public class Solution {
public static int findKthLargest(int[] nums, int k) {
shuffle(nums);
k = nums.length - k;
int low = 0;
int high = nums.length - 1;
while (low < high) {
final int pos = partition(nums, low, high);
if (pos < k) {
low = pos + 1;
} else if (pos > k) {
high = pos - 1;
} else
break;
}
return nums[k];
}
private static int partition(int[] a, int low, int high) {
int pivot = a[low]; // pick up the first element as pivot
while(low < high) {
while (low < high && a[high] >= pivot)
high--;
a[low] = a[high]; // from back to front find the first element smaller than pivot. Put to low.
while (low < high && a[low] <= pivot)
low++;
a[high] = a[low]; // from front to back find the first element than pivot. Put to high.
}
a[low] = pivot; // In the end, put pivot to low
return low;
}
private static void shuffle(int[] a) {
final Random random = new Random();
for (int index = 1; index < a.length; index++) {
final int r = random.nextInt(index + 1);
swap(a, index, r);
}
}
private static void swap(int[] a, int i, int j) {
final int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
public static void main(String args[]) {
Scanner cin = new Scanner(System.in);
int k = 2;
int[] nums = new int[6];
for (int i = 0; i < nums.length; i++) {
nums[i] = cin.nextInt();
}
int kthLargeNumber = findKthLargest(nums, k);
System.out.println(kthLargeNumber);
}
}