两种复杂度O(n)的方法
方法一:快速选择
class Solution { public int findKthLargest(int[] nums, int k) { int lo = 0, hi = nums.length - 1; // 当前partition 函数的区间边界 int target = nums.length - k; // 第 K 大的元素应该在什么位置 int cur = -1; // 存放partition函数的返回值 while(cur != target){ // 只要还没找到这个第 k 大 cur = partition(lo, hi, nums); if(cur < target){ lo = cur + 1; // 往右找 }else if(cur > target){ hi = cur - 1; // 往左找 } } return nums[cur]; } public void swap(int i, int j, int[] nums){ int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; } public int partition(int lo, int hi, int[] nums){ if(lo == hi) return lo; // 区间中只有一个元素,直接返回元素的索引 // 从区间中随机选个数 n,并将它先挪到整个区间最右边 int randIdx = lo + (int)(Math.random() * (hi - lo + 1)); int n = nums[randIdx]; swap(randIdx, hi, nums); // 利用双指针对整个区间进行分区 int l = lo, r = hi - 1; while(l < r){ while(l < r && nums[l] <= n) l ++; while(l < r && nums[r] > n) r --; swap(l, r, nums); } // 分区完成后再将 n 移动到正确的位置 if(nums[l] > n){ swap(l, hi, nums); return l; } return hi; } }
方法二 计数排序
class Solution { //采用计数排序 public int findKthLargest(int[] nums, int k) { if(nums==null || nums.length==0) return -1; int max=nums[0]; int min=nums[0]; for (int i = 1; i < nums.length; i++) { max = Math.max(max, nums[i]); min = Math.min(min, nums[i]); } int[] output = new int[max-min+1]; for (int i = 0; i < nums.length; i++) { output[nums[i]-min]++; } int count = 0; for (int i = output.length-1; i >= 0; i--) { count+=output[i]; if(count>=k) { return i+min; } } return -1; } }