快速排序和快速选择

快速排序

核心思路

通过分治和递归不断选择分界点,通过交换元素使分界点左边的元素小于分界点,右边的元素大于分界点。

实现方法

var sortArray = function(nums) {
    const quickSort = (left, right) => {
        if(left >= right) {
            return;
        }

        let i = left - 1, j = right + 1, x = nums[(i + j) >> 1];
        while(i < j) {
            do i++;
            while(nums[i] < x);
            do j--;
            while(nums[j] > x);
            if(i < j) {
                [nums[i], nums[j]] = [nums[j], nums[i]]
            }
        }
        quickSort(left, j);
        quickSort(j + 1, right);
    }
    quickSort(0, nums.length - 1);
    return nums;
};

求topK(快速选择)

只选择一侧区间递归,若在左侧区间,则是左侧区间的第k小个数,若在右侧区间,则是右侧区间的第k-sl小的数,sl为此时左侧区间的长度。

var findKthLargest = function(nums, k) {
    let resIndex = k;
    let quickSort = (left, right) => {
        if(left >= right) {
            return;
        }

        let i = left - 1, j = right + 1,  x = nums[(i + j) >> 1];
        while(i < j) {
            do i++;
            while(nums[i] > x);
            do j--;
            while(nums[j] < x);
            if(i < j) {
                [nums[i], nums[j]] = [nums[j], nums[i]];
            }
        }
        if(j - left + 1 >= k) quickSort(left, j);
        else {
            k = k - j + left - 1;
            quickSort(j + 1, right);
        }
    }
    quickSort(0, nums.length - 1);
    return nums[resIndex - 1];
};

这里需要不断改变k的值的原因是,i 和 j 的取值是由left和right决定的,而left和right又是不断变化的,原始k的值是根据 0 和 nums.length决定,所以需要在排序过程中不断的改变。

其次,把k看作一个数量,即nums中最小的前k个数。如果sl = j - left + 1这个范围内是nums中最小的 sl 个数,如果 k 大于 sl,则后续只排右半部分。这时则不需要看前k个最小的数了,把前面的一部分删除,需要看 sr = right - j + 1 中前 k - j + left - 1小的数了。

posted @ 2022-11-23 20:56  雪之下。  阅读(81)  评论(0)    收藏  举报