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]; } }