230402、快速排序

文章介绍了随机化快速排序算法的实现过程,通过创建Random对象选择切分元素,避免最坏情况下的时间复杂度。算法包括确定切分元素位置的partition函数,以及递归处理子区间的quickSort函数。该方法提高了排序的效率,特别是在数组存在大量重复元素时。
摘要由CSDN通过智能技术生成

随机选择一个切分元素,将数组分成小于等于切分元素和大于等于切分元素的两个区间,将切分元素与小于等于切分元素的最后一个元素进行交换,即确定了切分元素排序后应在的位置,之后递归子区间,完成其他元素的排序,时间复杂度O(nlogn~n2)

具体实现,首先创建Random对象,用于确定随机切分元素,避免数组本身有序时,选择最左边元素为切分元素,需遍历剩余的所有元素才可确定切分元素排序后的位置,时间复杂度为O(n2),并且可以将等于pivot的元素平均分布在左右两个区间,避免一个区间内过多的重复元素,降低随机选择切分元素的效果。

确定切分元素排序后位置的过程定义为partition,首先确定随机切分元素,之后将其交换到数组的最前端,定义le变量,用于探索小于等于切分元素区间的右边第一个位置,定义ge变量,用于探索大于等于切分元素区间的左边第一个位置,当le<=ge,带等号可以在le=ge时继续比较,因为他俩相等时只到的元素可能从左边le++造成,但是对应的元素仍然小于pivot,le仍需++,也可能从右边ge--造成,直到的元素仍然大于pivot,ge仍需--,才可以将对应的元素包裹在正确的范围内,并且le<ge时要弹出不比较了,ge位于le左侧,说明ge对应的元素要小于等于pivot了,下面找ge对应的的位置(大于等于pivot的区间的右边的第一个元素)就不用比较了,le指向的元素严格小于切分元素时,le才右移,ge指向的元素严格大于切分元素时,ge才左移,当两个变量都停止移动时,说明对应的元素应该交换到对面的区间,进行交换,移动le,ge变量,之后循环移动,交换,直至le≥ge,结束循环,交换切分元素与ge对应的变量,返回切分元素排序后的位置,即ge变量的值。


若le=ge,并且停止移动啦,说明两个变量指向的元素为切分元素,将最左端的切分元素与他们两个指向的变量交换即可,确定切分元素排序后位置。
当le>ge时,若le先停止移动,说明le对应的元素大于切分元素,ge需要跨过它,才可以将其纳入大于等于切分元素的区间,跨过之后,ge位于le的左侧,ge对应的元素小于等于切分元素,将其与最左端的切分元素进行交换,确定切分元素排序后的位置。若ge先停止移动,说明ge对应的元素小于切分元素,le跨过它,才可以将其纳入小于等于切分元素的区间,跨过之后,le位于ge的右侧,对应的元素大于等于切分元素,ge对应的元素小于切分元素,将其与最左端的切分元素进行交换,确定切分元素排序后的位置。

LeetCode912代码,参考liweiwei大佬b站快排讲解学习。

class Solution {
    Random random = new Random();

    public int[] sortArray(int[] nums) {
        quickSort(nums, 0, nums.length - 1);
        return nums;
    }

    public void quickSort(int[] nums, int left, int right) {
        if (left >= right) return;
        int pivotIndex = partition(nums, left, right);
        quickSort(nums, left, pivotIndex - 1);
        quickSort(nums, pivotIndex + 1, right);
    }

    public int partition(int[] nums, int left, int right) {
        int randomIndex = left + random.nextInt(right - left + 1);
        swap(nums, left, randomIndex);
        int pivot = nums[left];
        int le = left + 1;
        int ge = right;
        while (true) {
            while (le <= ge && nums[le] < pivot) {
                le++;
            }
            while (le <= ge && nums[ge] > pivot) {
                ge--;
            }
            if (le >= ge) {
                break;
            }
            swap(nums, le, ge);
            le++;
            ge--;
        }
        swap(nums, left, ge);
        return ge;
    }

    public void swap(int[] nums, int x, int y) {
        int temp = nums[x];
        nums[x] = nums[y];
        nums[y] = temp;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值