算法-快速排序(Java)

在这里插入图片描述
最近在看左神的算法课,理解之后在此将代码记录下来
问题一:

给定一个数组arr,和一个数num,请把小于等于num的数放在数组的左边,大于num的数放在数组的右边。要求额外空间复杂度O(1),时间复杂度O(N)

问题二(荷兰国旗问题):

给定一个数组arr,和一个数num,请把小于num的数放在数组的左边,等于num的数放在数组的中间,大于num的数放在数组的右边。

问题二代码:

    /**
     * 划分
     * @param arr 待划分数组
     * @param l 数组左边界
     * @param r 数组右边界
     * @param target 目标数
     * @return 与目标数相等的在划分后数组中的范围
     */
    private static int[] partition(int[] arr, int l, int r, int target) {
        int less = l - 1;//小于目标数在数组中的边界,默认不存在
        int more = r + 1;//大于目标数在数组中的边界,默认不存在
        int cur = l;//数组当前位置索引
        while (cur < more) {
            if (arr[cur] < target) {//当前数 < 目标数
                //把小于目标数的边界的下一个数与当前数交换//++less代表less+1之后,
                //cur++代表cur+1之前
                swap(arr, ++less, cur++);
            } else if (arr[cur] > target) {//当前数 > 目标数
                //把大于目标数的边界的前一个数与当前数交换,
                // 交换完之后不确定当前数是否小于目标数,当前位置不变,进行下一轮
                swap(arr, --more, cur);
            } else {//当前数 = 目标数
                cur++;
            }
        }
        return new int[]{less + 1, more - 1};
    }

    /**
     * 交换数组中i和j的位置
     *
     * @param arr 数组
     * @param i   i
     * @param j   j
     */
    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

经典快排

将数组的最后一个数X作为基准,划分成左边均为小于等于X,右边均大于X的数组,然后保留X的位置,继续将X左边的数组和右边的数组进行同样的划分
注:这样每次只能排好一个数,并且如果X前面的值全部大于或小于X,这个时候时间复杂度为O(N^2)

在这里插入图片描述
代码

	/**
     * 经典快排
     * @param arr 待排的数组
     * @param l   数组左边界
     * @param r   数组右边界
     */
    private static void classicQuickSort(int[] arr, int l, int r) {
        if (l < r) {
            int partition = partition(arr, l, r);//把l->r组成的数组进行划分[<=x , x , >x],x为数组最后一个数
            classicQuickSort(arr, l, partition - 1);//划分 <=x 部分
            classicQuickSort(arr, partition + 1, r);//划分 >x 部分
        }
    }
    /**
     * 划分
     *
     * @param arr 待划分数组
     * @param l   数组左边界
     * @param r   数组右边界
     * @return 待排数组最后一个数排完的位置
     */
    private static int partition(int[] arr, int l, int r) {
        int less = l - 1;
        int more = r;
        while (l < more) {
            if (arr[l] <= arr[r]) {
                swap(arr, l++, ++less);
            } else {
                swap(arr, l, --more);
            }
        }
        swap(arr, more, r);
        return more;
    }

    /**
     * 交换数组中i和j的位置
     *
     * @param arr 数组
     * @param i   i
     * @param j   j
     */
    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

随机快排

在数组中随机选择一个数,将其与数组最后一个数交换,然后把最后一个数X作为基准,划分为左边小于X,右边大于X的数组,然后保留等于X的部分,继续划分小于X和大于X的部分
注:这样每次可以将整个X排完整,并且最坏和最好的时间复杂度都是随机的

在这里插入图片描述
代码

   /**
     * 快速排序
     *
     * @param arr 待排的数组
     * @param l   数组左边界
     * @param r   数组右边界
     */
    private static void quickSort(int[] arr, int l, int r) {
        if (l < r) {
        	swap(arr, l + (int) (Math.random() * (r - l + 1)), r);//将数组中任意位置中的数与最后一个数交换
            int[] partition = partition(arr, l, r);//把l->r组成的数组进行划分[<x , x, >x],x为数组最后一个数
            quickSort(arr, l, partition[0] - 1);//划分 <x 部分
            quickSort(arr, partition[1] + 1, r);//划分 >x 部分
        }
    }

    /**
     * 划分
     *
     * @param arr 待划分数组
     * @param l   数组左边界
     * @param r   数组右边界
     * @return 等于x部分在数组中的范围
     */
    private static int[] partition(int[] arr, int l, int r) {
        int less = l - 1;//指向<x的最大索引位
        int more = r;//指向>x的最大索引位
        while (l < more) {//当前位置小于>x的最大索引位
            if (arr[l] < arr[r]) {//当前位置值<最后一个数
                swap(arr, l++, ++less);//当前值与<x的索引位下一个值交换,当前位置+1
            } else if (arr[l] > arr[r]) {//当前位置值>最后一个数
                swap(arr, l, --more);//当前值与>x的索引位前一个值交换
            } else {
                l++;
            }
        }
        //此时more指向的是>=最后一个数的边界
        swap(arr, more++, r);//将more位置的数和最后一个数交换,more+1代表more为>x数组的左边界
        return new int[]{less + 1, more - 1};
    }

    /**
     * 交换数组中i和j的位置
     *
     * @param arr 数组
     * @param i   i
     * @param j   j
     */
    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值