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.函數
Note: You may assume k is always valid, 1 ≤ k ≤ array's length.ui
時間 O(NlogK) 空間 O(K)指針
遍歷數組時將數字加入優先隊列(堆),一旦堆的大小大於k就將堆頂元素去除,確保堆的大小爲k。遍歷完後堆頂就是返回值。code
public class Solution { public int findKthLargest(int[] nums, int k) { PriorityQueue<Integer> p = new PriorityQueue<Integer>(); for(int i = 0 ; i < nums.length; i++){ p.add(nums[i]); if(p.size()>k) p.poll(); } return p.poll(); } }
時間 O(NlogN) 空間 O(1)排序
將數組排序後,返回第k個元素。隊列
public class Solution { public int findKthLargest(int[] nums, int k) { Arrays.sort(nums); return nums[nums.length - k]; } }
時間 Avg O(N) Worst O(N^2) 空間 O(1)element
跟快速排序一個思路。先取一個樞紐值,將數組中小於樞紐值的放在左邊,大於樞紐值的放在右邊,具體方法是用左右兩個指針,若是他們小於樞紐值則將他們換到對面,一輪事後記得將樞紐值賦回分界點。若是這個分界點是k,說明分界點的數就是第k個數。不然,若是分界點大於k,則在左半邊作一樣的搜索。若是分界點小於k,則在右半邊作一樣的搜索。it
helper函數的k
是k-1
,由於咱們下標從0開始的,咱們要比較k
和下標,來肯定是否左半部分有k個數字。io
互換左右時,也要先判斷left <= right
public class Solution { public int findKthLargest(int[] nums, int k) { return quickSelect(nums, k - 1, 0, nums.length - 1); } private int quickSelect(int[] arr, int k, int left, int right){ int pivot = arr[(left + right) / 2]; int orgL = left, orgR = right; while(left <= right){ // 從右向左找到第一個小於樞紐值的數 while(arr[left] > pivot){ left ++; } // 從左向右找到第一個大於樞紐值的數 while(arr[right] < pivot){ right --; } // 將兩個數互換 if(left <= right){ swap(arr, left, right); left ++; right --; } } // 最後退出的狀況應該是右指針在左指針左邊一格 // 這時若是右指針還大於等於k,說明kth在左半邊 if(orgL < right && k <= right) return quickSelect(arr, k, orgL, right); // 這時若是左指針還小於等於k,說明kth在右半邊 if(left < orgR && k >= left) return quickSelect(arr, k, left, orgR); return arr[k]; } private void swap(int[] arr, int idx1, int idx2){ int tmp = arr[idx1] + arr[idx2]; arr[idx1] = tmp - arr[idx1]; arr[idx2] = tmp - arr[idx2]; } }