描述
有一个整数数组,请你根据快速排序的思路,找出数组中第 k 大的数。
给定一个整数数组 a ,同时给定它的大小n和要找的 k ,请返回第 k 大的数(包括重复的元素,不用去重),保证答案存在。
要求:时间复杂度 O(nlogn),空间复杂度O(1)
数据范围:0≤n≤1000, 1≤K≤n,数组中每个元素满足0≤val≤10000000
示例1
输入:[1,3,5,2,2],5,3
返回值:2
示例2
输入:[10,10,9,9,8,7,5,6,4,3,4,2],12,3
返回值:9
说明:
去重后的第3大是8,但本题要求包含重复的元素,不用去重,所以输出9
第K大,因此下标为n-k
import java.util.*;
public class Solution {
public int findKth(int[] a, int n, int K) {
// write code here
Arrays.sort(a);
return a[n-K];
}
}
快排方式:双指针方式遍历,一旦比基数小则换,而基准归位时,由于是升序,则基准大于最后一个位置时,才调换【如果不剪枝直接调换会造成大于基准的值放到最左边,导致排序出错】,递归时加上该基准值递归,一轮调换后也许当前下标的后面并不一定都是小于该值的比如:arr->56184,一轮后54186,此时l=r=3(值为8),这个时候基准不能换,那么后续则不能递归下一轮。
import java.util.Arrays;
public class HeapDemo {
public static void main(String[] args) {
int arr[] = new int[]{9,8,7,6,5,4,3,2,1};
int left = 0,right = arr.length-1;
quickSort(arr,left,right);
Arrays.stream(arr).forEach(System.out::print);
}
private static void quickSort(int[] arr, int left, int right) {
int l = left,r = right;
if(left>=right) return;
int base = arr[left];
while (l<r){
while (arr[l]<=base && l<r) l++;
while (arr[r]>=base && l<r) r--;
if(l<r){
int swap = arr[l];
arr[l] = arr[r];
arr[r] = swap;
}
}
// 基准归位
if(arr[left]>arr[l]) {
arr[left] = arr[l];
arr[l] = base;
}
quickSort(arr,left,r-1);
quickSort(arr,r,right);
}
}
或者
l = left+1;r = right
while(true){
while (l<=right && arr[l]<=base ) l++;
while (r>=left+1 && arr[r]>=base) r--;
if(l>r) break;
swap(arr,l,r);
l++;r--;
}
swap(arr,left,r);// r会到基准的位置
quickSort(arr,left,r-1);
quickSort(arr,r+1,right);
这里l<=r,也可以,让r到基准位置