代码如下,基于快速排序,但是只根据要找寻的前k个目标,对部分区域进行排序。
public class QuickSelectSort {
public static void main(String[] args) {
int[] nums=new int[]{13,81,92,43,65,31,57,26,75,0};
new QuickSelectSort().quickSelectSort(nums,0,nums.length-1,1); //k为1代表前两个元素小于等于后面所有元素。
Arrays.stream(nums).forEach(System.out::println);
}
/**
* 快速排序:内部排序算法(不需要太多的空间),采用分治+递归
*
* 一次排序之后,枢纽元昨天的元素都小于等于枢纽元,枢纽元右边的元素都大于等于枢纽元。
* @param nums
* @param start
* @param end
*/
public void quickSelectSort(int[] nums, int start, int end, int k){
if(start<end) { //递归结束条件
int pivot = nums[start]; //枢纽元,防止被覆盖,需要先存起来。
int i = start;
int j = end;
while(i<j){
//因为枢纽元取的最左边的元素,所以
while(i<j&&nums[j]>=pivot){ //等于枢纽元的情况被放到了右边
j--;
}
if(i<j){
nums[i++]=nums[j]; //将右边小于枢纽元的数据放到左边来。此刻把枢纽元想象到已经在右边。
}
while(i<j&&nums[i]<pivot){ //注意这里没有等号,因为等于枢纽元的情况被放到了右边,左边不能等于枢纽元,比如【5,2,5,4,3,5,1,5】
i++;
}
if(i<j){
nums[j--]=nums[i];
}
//最后当i=j是,将枢纽元放置到最后的位置
nums[i]=pivot;
if(k==i){
return;
}else if(k<i) {
quickSelectSort(nums, start, i - 1,k);
}else {
quickSelectSort(nums, i + 1, end,k);
}
}
}
}
}
分析一下时间复杂度:
T(n)=n+(n/2+n/4+...+n/2^n)=O(n)