原题链接
思路:
- 利用快排的思想,找到能够区分 k 个 和 n-k 个元素的轴值下标k,输出前 k个元素即可。
- 代码分三部分写,分段、判断分段结果函数、初始函数。
- 注意的地方是 partition 函数中判断是否要继续 --right 或者 ++left 的条件中,轴值与数组元素需要至少保持一个有等于的情况,如果两个判断都没有等于的情况,那么会造成无限循环。原因是,如果在等于轴值的地方内层第一个 while 循环退出,在会把 nums[left] 位置的值换成轴值,相应的内层下一个 while 则不进入,left 不改变,进一步把 nums[right] 也设置成了轴值,所以下一次外层 while 循环的时候,直接卡在了内层的第一个while 上。无线循环的结构是外层的 while 结构。
int partition(int* nums, int left, int right){
int pivot = nums[left];
while(left < right){
while(left < right && nums[right] >= pivot) --right;
nums[left] = nums[right];
while(left < right && nums[left] <= pivot) ++left;
nums[right] = nums[left];
}
nums[left] = pivot;
return left;
}
int* quickSort(int* arr, int left, int right, int k){
if(left < right){
int pivotpos = partition(arr, left, right);
if(pivotpos == k) return arr;
if(pivotpos < k) return quickSort(arr,pivotpos + 1, right, k);
if(pivotpos > k) return quickSort(arr, left, pivotpos - 1, k);
}
return arr;
}
int* getLeastNumbers(int* arr, int arrSize, int k, int* returnSize){
if(arrSize == 0 || k == 0 || arrSize < k){
*returnSize = 0;
return arr;
}
*returnSize = k;
return quickSort(arr, 0 , arrSize -1 , k );
}