[路飞]_程序员必刷力扣题: 75. 颜色分类

163 阅读2分钟

75. 颜色分类

给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

示例 1:

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

示例 2:

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

示例3:

输入: nums = [0]
输出: [0]

示例4:

输入: nums = [1]
输出: [1]

提示:

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

进阶:

  • 你可以不使用代码库中的排序函数来解决这道题吗?
  • 你能想出一个仅使用常数空间的一趟扫描算法吗?

搞笑sort

进阶中的最后一句话提醒我们用代码库中的排序函数,直接搞定,当然这不是我们的目的

var sortColors = function (nums) {
    return nums.sort((a,b)=>a-b)
}

双指针

思路

我们可以声明两个变量p0和p1用来代表

分界点:

0和1之间的分界点p0

1和2之间的分界点p1

位置区间:

0所在的位置 [0,p0) 不包括p0

1所在的位置[p0,p1)

2所在的位置 [p1,len-1]

具体实现步骤:

  • 跟据以上分析,声明p0和p1都从0的位置开始

  • 遍历数组nums,拿出第i项的值item

    • 如果item===0,此时我们需要把i的值交换到p0的位置,交换完毕后,因为原来p0的位置增加了一个有效数字0,而且p1是在p0之后一定是大于等于p0的,所以p0和p1都需要向后移动
    • 如果item===1,需要交换i和p1位置的值,交换完毕后,因为原来p1的位置增加了一个有效数字1,所以p1需要往后挪动一位,而p0因为是在p1之前,所以不需要挪动
  • 导致的问题:

    • 如果p0不等于p1,证明已经找到过数字1并且交换放入到p1的位置,那么此时,p0必然指向已经排好序的数字1的位置,如果再次发现0并且直接和p0交换,会导致已经拍好序的1又被打乱
    • 解决: 因此我们需要在0交换到p0后再讲位于i的数字1重新放入p1的位置
var sortColors = function (nums) {
    var p0 = 0
    var p1 = 0
    for (var i = 0; i < nums.length; i++) {
        var item = nums[i]
        if (item === 0) {
            //交换位置
            swap(nums, i, p0)
            //如果p0不等于p1则 交换会导致已经整理好的位于p0的1被换走,所以需要再次交换i和p1保证p1都在一起而不会乱
            if (p0 !== p1)  {
                swap(nums, i, p1)
            }
            //交换后两者位置都要往后移动一位
            p0++
            p1++

        }
        if (item === 1) {
            swap(nums, i, p1)
            p1++
        }
    }
    function swap(nums,i1,i2){
        if(i1===i2) return
        var temp = nums[i1]
        nums[i1] = nums[i2]
        nums[i2] = temp
    }
};