问题:数组
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.函数
For example,
Given [3,2,1,5,6,4]
and k = 2, return 5.ui
Note:
You may assume k is always valid, 1 ≤ k ≤ array's length.指针
解决:code
① 找到第k大的数,能够存在重复。时间 O(NlogN) 空间 O(1)排序
class Solution {//6ms
public int findKthLargest(int[] nums, int k) {
Arrays.sort(nums);
return nums[nums.length - k];
}
}队列
② 使用优先队列,遍历数组时将数字加入优先队列(堆),一旦堆的大小大于k就将堆顶元素去除,确保堆的大小为k。遍历完后堆顶就是返回值。时间 O(NlogK) 空间 O(K)element
class Solution {//18ms
public int findKthLargest(int[] nums, int k) {
PriorityQueue<Integer> p = new PriorityQueue<>();
for (int i = 0;i < nums.length ;i ++ ) {
p.add(nums[i]);
if (p.size() > k) {
p.poll();
}
}
return p.poll();
}
}it
③ 快速选择 Quick Select,跟快速排序一个思路。先取一个枢纽值,将数组中小于枢纽值的放在左边,大于枢纽值的放在右边,具体方法是用左右两个指针,若是他们小于枢纽值则将他们换到对面,一轮事后记得将枢纽值赋回分界点。若是这个分界点是k,说明分界点的数就是第k个数。不然,若是分界点大于k,则在左半边作一样的搜索。若是分界点小于k,则在右半边作一样的搜索。时间 Avg O(N) Worst O(N^2) 空间 O(1)。io
class Solution { //5ms
public int findKthLargest(int[] nums, int k) {
return quickSelect(nums,k - 1,0,nums.length - 1);
}
public int quickSelect(int[] nums,int k,int left,int right){
int pivot = nums[(left + right) / 2];
int orgL = left;
int orgR = right;
while(left <= right){
while(nums[left] > pivot){//从左到右找到第一个小于枢纽值得数
left ++;
}
while(nums[right] < pivot){//从右向左找到第一个大于枢纽值的数
right --;
}
if (left <= right) {//交换两个数
swap(nums,left,right);
left ++;
right --;
}
}
//最后退出的状况应该是右指针在左指针左边一格
//这时若是右指针还大于等于K,说明第k个数在左半边
if (orgL < right && k <= right) {
return quickSelect(nums,k,orgL,right);
}
if (left < orgR && k >= left) {
return quickSelect(nums,k,left,orgR);
}
return nums[k];
}
public void swap(int[] nums,int i,int j){
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
【注意】
dfs函数的k
是k-1
,由于咱们下标从0开始的,咱们要比较k
和下标,来肯定是否左半部分有k个数字。
互换左右时,也要先判断left <= right