215. Kth Largest Element in an Array
一、题目
1、审题
2、分析
在一个无序的整形数组中找出第 K 大的元素。
二、解答
1、思路:
方法一、
排序后直接返回。
1 public int findKthLargest1(int[] nums, int k) { 2 int len = nums.length; 3 Arrays.sort(nums); 4 return nums[len - k]; 5 }
方法二、采用 PriorityQueue
PriorityQueue 对进入的元素进行排序,每次出队的都是最小的元素;
1 public int findKthLargest2(int[] nums, int k) { 2 // 优先队列 3 PriorityQueue<Integer> pq = new PriorityQueue<>(); 4 for(int val: nums) { 5 pq.offer(val); 6 if(pq.size() > k) 7 pq.poll(); 8 } 9 return pq.peek(); 10 }
方法三、
1、对数组采用快速排序,确定第一个元素在有序时的下标 j
2、若 j == k 则返回此元素
若 j > k 则 high = j - 1; 在对数组左半部分进行快速排序;
若 j < k,则 low = j + 1; 在对数组右半部分进行快速排序;
直到 j == k, 返回此元素即可
1 public int findKthLargest3(int[] nums, int k) { 2 3 k = nums.length - k; 4 int low = 0, high = nums.length - 1; 5 while(low < high) { 6 int j = partition(nums, low, high); 7 if(j < k) 8 low = j + 1; 9 else if(j > k) 10 high = j - 1; 11 else 12 break; 13 } 14 return nums[k]; 15 } 16 17 //. 快速排序 18 private int partition(int[] nums, int low, int high) { 19 int i = low, j = high + 1; 20 while(true) { 21 while(i < high && nums[++i] < nums[low]); 22 while(j > low && nums[low] < nums[--j]); 23 if(i >= j) 24 break; 25 exchange(nums, i, j); 26 } 27 exchange(nums, low, j); 28 return j; 29 } 30 31 private void exchange(int[] nums, int i, int j) { 32 int tmp = nums[i]; 33 nums[i] = nums[j]; 34 nums[j] = tmp; 35 }
对方法三进行优化:
为了防止输入的是有序的元素,所造成的效率最差的情况,可以先对数组元素进行乱序。
1 public int findKthLargest(int[] nums, int k) { 2 shuffle(nums); 3 k = nums.length - k; 4 int low = 0; 5 int high = nums.length - 1; 6 while(low < high) { 7 int j = partition(nums, low, high); 8 if(j < k) 9 low = j + 1; 10 else if(j > k) 11 high = j - 1; 12 else 13 break; 14 } 15 return nums[k]; 16 } 17 18 // we can randomize the input, so that even when the worst case input would be provided the algorithm wouldn't be affected. 19 // So all what it is needed to be done is to shuffle the input. 20 private void shuffle(int[] nums) { 21 Random random = new Random(); 22 for (int i = 1; i < nums.length; i++) { 23 int r = random.nextInt(i + 1); 24 exchange(nums, i, r); 25 } 26 } 27 28 //. 快速排序 29 private int partition(int[] nums, int low, int high) { 30 int i = low, j = high + 1; 31 while(true) { 32 while(i < high && nums[++i] < nums[low]); 33 while(j > low && nums[low] < nums[--j]); 34 if(i >= j) 35 break; 36 exchange(nums, i, j); 37 } 38 exchange(nums, low, j); 39 return j; 40 } 41 42 private void exchange(int[] nums, int i, int j) { 43 int tmp = nums[i]; 44 nums[i] = nums[j]; 45 nums[j] = tmp; 46 }