题目:给一个无序数组,求前k个最小的数,排好序放到数组里输出。
public int[] getLeastNumbers(int[] arr, int k)
思路:1.先用快速排序,然后直接用Arrays.copyOf(arr,k)截取前k个元素并复制为新的数组返回,原数组不变。
快速排序(第一个元素为标准,且标准只在最后交换一次到中间)
快速排序是以第一个元素为标准,但是这个标准不移动,而是让其它元素进行交换移动,最后才把标准交换到中间。标准只交换一次。
快速排序自己实现实现
/*
快排,模板题,背模板
*/
public int[] getLeastNumbers(int[] arr, int k) {
qsort(arr,0,arr.length-1);
/*
Arrays.copyOf(int[] arr,int newLength)
可以截取arr前newLength个元素,并且复制出来。不改变原数组。
若newLength大于arr.length则多出来的默认补0
*/
int[] res = Arrays.copyOf(arr, k);
return res;
}
/*
快排思路:
nums[l]作为标准不动,i,j指针移动。
j从右往左移动找到一个小于标准的值,i从左往右移动找到一个大于标准的值。
然后i,j的值交换。
直到i,j重合后,把标准交换到中间
*/
public void qsort(int[] nums, int l, int r) {
/*
l>r可根据递归式子简单推断(是标准左边或右边没有元素的情况)
l==r是标准左边或右边只有一个元素的情况
*/
if(l >= r) return;
//i,j用来移动
int i = l,j = r;
/*
i等于j时重合,此时需要把标准交换过来。
否则i,j再变化就i大于j,无法让标准交换到中间了
*/
while(i < j){
/*
里面也可能先i等于j,等于就退出
nums[l]是标准
*/
while(i < j && nums[j] >= nums[l]) j--;
while(i < j && nums[i] <= nums[l]) i++;
//此时i等于j,交换
swap(nums,i,j);
}
//把标准交换到中间,nums[l]为标准
swap(nums,i,l);
//递归分为两部分
qsort(nums,l,i-1);
qsort(nums,i+1,r);
}
private void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
2.基于快排的优化方法
优化思路:当标准交换到下标为k时,该标准大于前面的(下标从0 1 … k-1,一共k个),小于后面的。所以这前k个就是要求的topk的最小值。
实际修改:只需要在递归时加上i与k的判断即可。(在qsortPro(nums,l,i-1) 和 qsortPro(nums,i+1,r) 加,当i不等于k时就往左或右区间移动就行了),i等于k是什么都不做,正好方法结束。
/*
快排,模板题,背模板
*/
public int[] getLeastNumbers(int[] arr, int k) {
qsortPro(arr,0,arr.length-1,k);
int[] res = Arrays.copyOf(arr, k);
return res;
}
public void qsortPro(int[] nums, int l, int r,int k) {
/*
l>r可根据递归式子简单推断(是标准左边或右边没有元素的情况)
l==r是标准左边或右边只有一个元素的情况
*/
if(l >= r) return;
//i,j用来移动
int i = l,j = r;
//i等于j时重合,此时需要把标准交换过来。否则i,j再变化就i大于j了
while(i < j){
/*
里面也可能先i等于j,等于就退出
nums[l]是标准
*/
while(i < j && nums[j] >= nums[l]) j--;
while(i < j && nums[i] <= nums[l]) i++;
//此时i等于j,交换
swap(nums,i,j);
}
//把标准交换到中间,nums[l]为标准
swap(nums,i,l);
//递归分为两部分
if(i > k) qsortPro(nums,l,i-1,k);
if(i < k) qsortPro(nums,i+1,r,k);
/*
i等于k时结束,此时标准的下标正好等于k
0 - k-1 正好为结果
*/
}
private void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}