每日算法220522分区快速排序的从0到1

Posted 如何在5年薪百万

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了每日算法220522分区快速排序的从0到1相关的知识,希望对你有一定的参考价值。

今日题目

快速排序

通过选择数组的最右侧数作为分隔符,将数组分割成小于区域,等于区域,大于区域,周而复始,最终将数组排序。

今日心得

  • 数组相关的算法,一旦出现大量的systemcopy就说明不是最优解,没有充分利用数组空间。
  • 递归虽然理解很难,但是理解了解答就会很简单。只需要关注构建最小算法模型和边界条件。反而,使用非递归法的边界十分困难,非常容易出错。
  • 如果能画出纸上的过程,代码就实现了一半。否则,代码会卡在边界条件处理上,绕不出。

算法编码

package sort;

/**
 * @ClassName QuickSort
 * @Description 快速排序
 * <p>数组题一旦有太多copy就说明不是最优解,没有充分利用空间</p>
 * @Author kouryoushine
 * @Date 2022/5/22 10:20
 * @Version 1.0
 */
public class QuickSort 

    public static void main(String[] args) 
        int[] arr = 1, 3, 7, 5, 4, 3, 9, 8, 3, 7, 2, 3, 5, 7;
        quickSort(arr);
        for (int a = 0; a < arr.length; a++) 
            System.out.println(arr[a]);
        
    

    //用arr的最右数做区分,<=Rnum的放在左边,>Rnum的放在右边
    public static void splitByRnum(int[] arr) 
        if (arr == null || arr.length == 0) 
            return;
        
        int N = arr.length;
        int lessArea = -1;
        int index = 0;
        ;
        int rNum = arr[N - 1];
        while (index < N)  //顺序遍历数组中每一个数
            if (arr[index] <= rNum)   //当前数比最右数小,则交换位置。最小区域又阔,下标右移。
                swap(arr, lessArea + 1, index);
                lessArea++;
                index++;
             else   //当前数比最右大,则跳过,下标右移
                index++;
            
        

    

    /**
     * 根据数组最右的值,将数据拆分成三个区域
     * 小区域:less=-1
     * 大区域:more=N-1
     * 等于区域: [less+1:more-1]
     * <p>
     * 实现逻辑:
     * index沿array遍历
     * 见代码注释
     *
     * @param arr
     */
    public static void splitNumByRnumIntoThreeAre(int arr[]) 
        int N = arr.length;
        int less = -1; //小区域有边界
        int more = N - 1; //大区域左边界
        int rNum = arr[N - 1];
        int index = 0; //下标
        while (index < more) 
            if (arr[index] < rNum) 
                swap(arr, less + 1, index);//小区域下一个数和当前值交换,下标和小区域右移
                index++;
                less++;
             else if (arr[index] > rNum)  //大区域前一个值和当前值交换,大区域左移。index不变
                swap(arr, more - 1, index);
                more--;
                //index不变
             else  //跳过
                index++;
            

        
        //index=more时
        swap(arr, index, N - 1);

    

    /**
     * 分区快排,将上面能力进一步抽象为L...R范围内的排序,过程一样。
     *
     * @return ==区域的左右边界
     */

    public static int[] partiion(int[] arr, int L, int R) 
        int lessR = L - 1;
        int moreL = R;
        int rNum = arr[R];
        int index = L;
        while (index < moreL) 
            if (arr[index] < rNum) 
                swap(arr, lessR + 1, index);//小区域下一个数和当前值交换,下标和小区域右移
                index++;
                lessR++;
             else if (arr[index] > rNum)  //大区域前一个值和当前值交换,大区域左移。index不变
                swap(arr, moreL - 1, index);
                moreL--;
                //index不变
             else  //跳过
                index++;
            
        
        swap(arr, R, index);
        return new int[]lessR + 1, moreL; //moreL而不是moreL-1画出内存就知道了
    

    public static void quickSort(int arr[]) 
        if (arr == null || arr.length < 2) 
            return;
        
        process(arr, 0, arr.length - 1);


    

    //递归函数
    public static void process(int[] arr, int L, int R) 
        if (L >= R) 
            return;
        
        int[] equal = partiion(arr, L, R);//拆分成三个区域
        int L1 = L;
        int R1 = equal[0] - 1;
        int L2 = equal[1] + 1;
        int R2 = R;
        process(arr, L1, R1);
        process(arr, L2, R2);


    


    public static void swap(int arr[], int i, int j) 
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    


以上是关于每日算法220522分区快速排序的从0到1的主要内容,如果未能解决你的问题,请参考以下文章

每日算法220522分区快速排序的从0到1

每日算法快速排序

快速排序算法(LeetCode版)

经典算法之快速选择算法

每日一算法|快速排序---第三天

快速排序算法学习(C语言和python代码对比)