75. 颜色分类

521 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情

每日刷题 2021.04.02

题目

  • 给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
  • 我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
  • 必须在不使用库的sort函数的情况下解决这个问题。

示例

  • 示例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] 为 01 或 2

解题思路

  • 思路分析:需要会快速排序的思想。
  • 在循环变量i遍历的过程中,认为定义的循环不变的性质,决定了[初始化]、[遍历过程]和[循环终止]条件

本题思路

  • 初始化:三个区间
    • [0,l) => l以前的元素全部为0
    • [l,r] => 中间的全部为1
    • (r,len - 1] => r以后的全部为2
    • 分析:初始化的时候需要将这三个区间全部为0,即:l = 0, r = len - 1,此时三个区间正好覆盖了整个数组
  • 遍历过程:需要一个中间变量i
    • nums[i] == 0时,需要将其放到第一个区间中
    • nums[i] == 2时,需要将其放在第三个区间中
    • 中间的1不需要改变
    • 注意:左边的交换后,需要将i保留在当前位置
  • 循环终止:当i > r
    • Why? 因为:第三个区间(r, len- 1]中,已经确定了其全部为排好的2,因此不需要再继续往后进行判断,无意义。

AC代码

var sortColors = function(nums) {
  // 三个区间:左边一个区间 中间一个区间 右边一个区间
  let len = nums.length;
  let l = 0, r = len - 1,i = 0;
  while(i <= r) {
    if(nums[i] == 0){
      let tempt = nums[l];
      nums[l] = nums[i];
      nums[i] = tempt;
      l++;
    }else if(nums[i] == 2){
      // console.log(r,nums[r],i,nums[i])
      let tt = nums[r];
      nums[r] = nums[i];
      nums[i] = tt;
      // console.log('arr:', nums)
      r--;
      i--;
    }
    i++;
  }
};

总结

  • 循环不变量是写对代码、分析边界条件的基础