【快速排序】| 详解快速排序核心代码之颜色分块 力扣75

🎗️ 主页:小夜时雨
🎗️专栏:快速排序
🎗️如何活着,是我找寻的方向

优雅

1. 题目解析

题目链接: https://leetcode.cn/problems/sort-colors/description/

在这里插入图片描述

本道题是快速排序的核心代码区间, 后面的快速排序会用到这一思想,所以还是十分重要的, 接下来我们来分析一下这道题目.

  • 首先我们注意到这个要求在原地进行排列, 若是使用辅助数组, 我们总头开始遍历原数组, 以此先找出所有的 0 放在辅助数组中, 之后是找到所有的 1 放在辅助数组中 0 的后面, 最后是数字 2.
  • 这样算下来的时间复杂度则是O(N ^ 2), 题目要求是在原地进行, 所以这个方法是行不通的, 而且时间复杂度有点高, 接下来我们介绍一下三指针的用法,只需要遍历原数组一边,即可完成区域的划分.

具体实现过程:

  1. 创建三个变量 i, left, right, i 表示遍历原数组, left 用来标记排好之后 0 区域的最右侧, right 标记 2 区域的最左侧。

  2. 标记原因:排好之后 0 是在最左侧, 所以我们找到 0 区域的最右侧,那么 left 的左边区域都是 0, 右侧都是1, 同理 right 的右侧都是 2, 左侧都是 1,见下图更容易理解。

  3. 这样标记之后, 发现数组被分成了四个区域,[0, left] 这个位置都是 0, [left + 1, i] 这个区域都是 1, [i, right - 1] 是带扫描的区域,[right, n - 1] 都是 2 (n 是原数组的长度)。

  4. 扫描到 i 位置的时候, 需要进行判断 i 的值:
    1). nums[i] = 0, 那么需要把 0 放到 0 的区域, 那么也就是 left + 1 的后面, 此时只需要交换 left + 1 和 i 位置的值即可, 交换之后, left 和 i 同时向后加 1,即是

    swap(++left, i++, nums);

    2). nums[i] = 1,我们注意到 i 的左侧区域就是 [left + 1, i] 那么也就是 1 的区域, 此时只需要 i++ 即可。
    3). nums[i] = 2,right - 1 右侧的区域都是 2, 需要交换 right-1位置和 i 位置的值,

    注意:

    • 交换之后,right - 1位置原本的值我们是还没有进行判断的,不同于 nums[i] = 0,那个其实交换的是 nums[++left] = 0 和 nums[i] = 1, 交换的本质就是 0 和 1 位置的交换, 我们已经知道 nums[++left] = 1了。
    • 但是此处我们是不知道 nums[right - 1] 的值的,所以交换之后 right-1, 注意 i 要不变,不能向后加 1, 还需要再次进行判断原来 right -1 位置的值。
    • 所以代码是如下的写法: 而没有 i + 1。

      swap(–right, i, nums); 里面的是 - - right

接下来的代码里还会再次进行强调的,看下面的图更容易理解:
在这里插入图片描述

2. 代码

看下面的代码对照着上面的流程解析可能会更加的清楚。

   public void sortColors(int[] nums) {

       int n = nums.length;
       // left 标记 0 区域的最右侧,0 位置还没有遍历,是 i 的位置,所以left 从 -1 开始
       // right 标记 2 区域的最左侧, 也就是 n 的位置,i 遍历不到
       int left = -1, right = n;
       // [i, right - 1] 是带扫描区域, 当 i == right 的时候也就是 i 扫描完了
       for(int i = 0; i < right; ) {
           if(nums[i] == 0) {
               // left 标记0区域的最右的一个位置
               swap2(++left, i++, nums);
           } else if(nums[i] == 1) {
               // 中间的区域直接跳过
               i++;
           }else {
               // right 标记2区域的最左侧位置
               // 注意这个位置没有 i++
               swap2(--right, i, nums);
           }
       }
   }
   private void swap2(int left, int right, int[] nums) {
       int tmp = nums[left];
       nums[left] = nums[right];
       nums[right] = tmp;
   }

后面我们会讲解快速排序的实现流程。

🎗️🎗️🎗️ 好啦,到这里有关本题的分享就没了,如果感觉做的还不错的话可以点个赞,关注一下,你的支持就是我继续下去的动力,我们下期再见,拜了个拜~ ☆*: .。. o(≧▽≦)o .。.:*☆

  • 9
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值