• 【LeetCode力扣】75 快速排序的子过程partition(荷兰国旗问题)


    目录

    1、题目介绍

    2、解题思路

    2.1、冒泡排序暴力破解

    2.2、快速排序的子过程partition

    2.2.1、详细过程描述

    2.2.2、代码描述


    1、题目介绍

    原题链接:75. 颜色分类 - 力扣(LeetCode)

    示例 1:

    输入:nums = [2,0,2,1,1,0]

    输出:[0,0,1,1,2,2]

    示例 2:

    输入:nums = [2,0,1]

    输出:[0,1,2]

     提示:

    • n == nums.length
    • 1 <= n <= 300
    • nums[i] 为 0、1 或 2

    2、解题思路

    根据题目的意思,简单来说就是将数组里的数据按照0、1、2的顺序排列。

    如果只是要求排序,其实投机取巧的方式很多,比如直接使用冒泡排序也能完成此题。

    2.1、冒泡排序暴力破解

    1. void sortColors(int* nums, int sz) {
    2. int i = 0;
    3. int j = 0;
    4. for (i = 0; i < sz - 1; i++)
    5. {
    6. for (j = 0; j < sz - 1 - i; j++)
    7. {
    8. if (nums[j] > nums[j + 1])
    9. {
    10. int tmp = nums[j];
    11. nums[j] = nums[j + 1];
    12. nums[j + 1] = tmp;
    13. }
    14. }
    15. }
    16. }

    冒泡排序:时间复杂度为O(n^2),空间复杂度为O(1)

    2.2、快速排序的子过程partition

    但是根据题目的难度标识为中等,很明显这道题不是在考察冒泡排序的。 

    该题的难点在于如何原地遍历的情况下使得:时间复杂度为O(n),空间复杂度为O(1)。即仅使用常数空间的一趟扫描算法。

    而这里就用到了快速排序的子过程partition,partition能够通过一次遍历将所有元素按照标志数进行划分,小于放标志数左边,大于放标志数右边。

    首先这里有个数组,规定小num的值放在左侧,大于num的值放在右侧,而等于num的值放在中间,下面进行partition过程讲解。

    首先蓝色方框是小于num的区域,橙色方框是大于num的区域,i从0开始循环遍历。

    规则:

    1. 当arr[ i ]小于num时,arr[ i ]与小于区域的下一个元素交换位置,然后小于区域向右移动一位,i++。
    2. 当arr[ i ]等于num时,i++。
    3. 当arr[ i ]大于num时,arr[ i ]与大于区域的上一个元素交换位置,然后大于区域向左移动一位,此时i不自增
    2.2.1、详细过程描述

    首先arr[ i ] 等于3,小于5

    【执行规则1】3与小于区域的下一位元素交换位置,而此时小于区域的下一个元素就是3,因此交换其实已经完成了。然后小于区域向右移动一位,i++。

     此时arr[ i ] 等于5

    【执行规则2】直接 i++。

    此时arr[ i ] 等于6,大于5

    【执行规则3】3与大于区域的上一位元素交换位置,于是6和8交换位置。然后大于区域向左移动一位。

     此时arr[ i ] 等于8,大于5

    【执行规则3】8与大于区域的上一位元素交换位置,于是8和第二个5交换位置。然后大于区域向左移动一位。

     此时arr[ i ] 等于5

    【执行规则2】直接 i++。

     此时arr[ i ] 等于7,大于5

    【执行规则3】7与大于区域的上一位元素交换位置,于是7和第二个3交换位置。然后大于区域向左移动一位。

    此时arr[ i ] 等于3,小于5

    【执行规则1】3与小于区域的下一位元素交换位置,于是第一个5和第二个3交换位置。然后小于区域向右移动一位,i++。

     此时arr[ i ] 等于4,小于5

    【执行规则1】4与小于区域的下一位元素交换位置,于是第一个5和4交换位置。然后小于区域向右移动一位,i++。

    此时i遇到了大于区域了,就停止执行,此时数组中的值就变成了左边小右边大中间等于。

    2.2.2、代码描述

    按照快速排序的子过程partition的方法,改造代码 ,使标志数为1,然后将小于1的放左边,大于1的放右边,既完成排序。

    1. void sortColors(int* nums, int numsSize){
    2. int signal = 1; //标志数
    3. int i = 0;
    4. int left = -1; //left为下标,是小于区域的右边界,刚开始还未进入数组,因此为-1
    5. int right = numsSize; //right为下标,是大于区域的左边界,刚开始还未进入数组,因此为numsSize
    6. while(i//当i遇上大于区域时停止循环,此时就完成了排序
    7. {
    8. if(nums[i] < signal) //当nums[i]小于标志数
    9. {
    10. int tmp = nums[left+1]; //交换小于区域的下一个元素
    11. nums[left+1] = nums[i];
    12. nums[i] = tmp;
    13. left++;
    14. i++;
    15. }
    16. else if(nums[i] > signal) //当nums[i]大于标志数
    17. {
    18. int tmp = nums[right-1]; //交换大于区域的上一个元素
    19. nums[right-1] = nums[i];
    20. nums[i] = tmp;
    21. right--;
    22. }
    23. else
    24. {
    25. i++; //等于时直接i++
    26. }
    27. }
    28. }

    快速排序的子过程partition:时间复杂度为O(n),空间复杂度为O(1) 

    如果觉得作者写的不错,求给博主一个大大的点赞支持一下,你们的支持是我更新的最大动力!

    如果觉得作者写的不错,求给博主一个大大的点赞支持一下,你们的支持是我更新的最大动力!

    如果觉得作者写的不错,求给博主一个大大的点赞支持一下,你们的支持是我更新的最大动力!

  • 相关阅读:
    Ajax--form表单与模板引擎--模板引擎的基本概念 - art-template模板引擎
    FreeRTOS个人笔记-软件定时器
    大势&山维 | 全盘自主可控的实景三维中国建设解决方案
    网络安全内网渗透之信息收集--systeminfo查看电脑有无加域
    【LeetCode高频SQL50题-基础版】打卡第1天:第1~10题
    【最全日期获取合集】js获取昨天,今天,明天,上周,本周,下周,上月,本月,下月,去年,本年,明年,上季度,本季度,下季度,向前推日期等【全覆盖,拿来即用】
    基于java+ssm教学质量评价系统(学生评教)-计算机毕业设计
    136.如何进行离线计算-2
    解决“ImportError: DLL load failed while importing _rust: 找不到指定的程序的问题
    matlab实现QPSK信号的产生与调制
  • 原文地址:https://blog.csdn.net/zzzzzhxxx/article/details/133785886