快速排序
快速排序的一般写法。下面的写法是双指针双向而行。区分交汇点左侧的值和右侧的值。
void QuickSort(int R[], int lo, int hi){
int i = lo, j = hi;
int temp;
if(i < j){
temp = R[i];
while (i != j)
{
while(j > i && R[j] > temp)-- j;
R[i] = R[j];
while(i < j && R[i] < temp)++ i;
R[j] = R[i];
}
R[i] = temp;
QuickSort(R, lo, i - 1);
QuickSort(R, i + 1, hi);
}
}
在取前面的最小的 k 个数的算法题中,可以在快排基础上做优化。
/**
* @param {number[]} arr
* @param {number} k
* @return {number[]}
*/
var getLeastNumbers = function(arr, k) {
if (k === 0) {
return [];
}
if (arr.length <= k) {
return arr;
}
quickSort(arr, 0, arr.length-1, k-1);
return arr.slice(0, k);
};
function quickSort(arr, left, right, target) {
const mid = partition(arr, left, right);
if (mid === target) {
return;
}
mid > target ? quickSort(arr, left, mid-1, target) : quickSort(arr, mid+1, right, target);
}
function partition(arr, left, right) {
const flag = arr[right];
let i = left-1;
for (let j = left; j < right; j++) {
if (arr[j] <= flag) {
swap(arr, ++i, j);
}
}
swap(arr, ++i, right);
return i;
}
function swap(arr, i, j) {
[arr[i], arr[j]] = [arr[j], arr[i]];
}
这里的 partition 和前面不同,使用的双指针是同向而行的,碰到较小值就交换位置。
function partition(arr, left, right) {
const flag = arr[right];
let i = left-1;
for (let j = left; j < right; j++) {
if (arr[j] <= flag) {
swap(arr, ++i, j);
}
}
swap(arr, ++i, right);
return i;
}
针对前 k 个数做优化。如果前 k 个数排好就返回。如果排序左侧范围太大就缩小范围,如果左侧范围太小就排序剩余部分。
function quickSort(arr, left, right, target) {
const mid = partition(arr, left, right);
if (mid === target) {
return;
}
mid > target ? quickSort(arr, left, mid-1, target) : quickSort(arr, mid+1, right, target);
}
最后更新于