問題:數組
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