算法通关村第10关【青铜】| 快速排序各种写法

思路:

指定一个数字,将数组比他小的放到左边,比他大的放到右边,实现归位

然后再指定一个数字递归,一直遍历完数组

最好的情况每次指定的都是中间位置的数字,划分完后两边长度相等,2T(n/2) + O(n),复杂度O(nlog(n))

可以证明,平均情况下的时间复杂度也是O(nlog(n))

最坏的情况,每次指定的都是最小的数字,n的复杂度归位,一共n次,T(n-1) + O(n),复杂度O(n^2)

方式一、对撞型指针+指定头元素

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

    public void trace(int[] nums,int start,int end) {
        if(start>=end){
            return;
        }
        int p = nums[start];
        int l = start;
        int r = end;
        while(l<r){
            while(nums[r]>=p&&l<r){
                r--;
            }
            nums[l] = nums[r];
            while(nums[l]<=p&&l<r){
                l++;
            }
            nums[r] = nums[l];
        }
        nums[l] = p;
        trace(nums,l + 1,end);
        trace(nums,start,l-1);
    }


}

方式二、对撞型指针+指定中间

这里要注意的细节很多,判断条件的时候nums[l]>p不能等于,不然左指针会跑到右边去同理右边

同时l<=r,不能是小于

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

    public void trace(int[] nums,int start,int end) {
        if(start>=end){
            return;
        }
        int p = nums[(start+end)/2];
        int l = start;
        int r = end;
        while(l<=r){
            while(nums[r]>p&&l<=r){
                r--;
            }
            while(nums[l]<p&&l<=r){
                l++;
            }
            if(l<=r){
                swap(nums,l,r);
                l++;
                r--;
            }
        }
        trace(nums,start,r);
        trace(nums,l,end);
    }

     private void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }

}

方式三、快慢指针+指定尾元素

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

    public void partition(int[] nums, int l, int r) {
        if(l<r){
            int pivot = nums[r];
            int i = l - 1;
            //快慢指针找到目标位置
            for (int j = l; j <= r - 1; ++j) {
                if (nums[j] <= pivot) {
                    i = i + 1;
                    swap(nums, i, j);
                }
            }
            //放置目标元素
            swap(nums, i + 1, r);
            int p = i+1;
            //递归
            partition(nums,l,p-1);
            partition(nums,p+1,r);
        }
    }
    private void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值