Leetcode 75.颜色分类

72 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第6天,点击查看活动详情

1.题目

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

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

必须在不使用库的sort函数的情况下解决这个问题。

示例 1:

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

2.思路

本题需要我们在原地排序,将一个乱序的且只包含0,1,2的数组重排为升序数组。首先我们可以考虑为手写一个排序,将数组按照升序重排一遍就可以达到目标了。但是这样的话会造成不必要的消耗,因为我们确定有0,1,2三种数字,所以我们只需要针对这三个数字排序就可以了。

首先我们创建一个变量index用于保存当前已排序数字位置,然后进行一轮遍历,如果数字为0就将其与index位置的变量交换位置,并将index+1,然后判断下一个数字直到遍历结束,此时我们就得到了一个数字0在最前面,后面是1和2的数组了,然后我们从index的位置开始再遍历一遍,这次我们将所有等于1的数字进行一个交换放到0的后面,这样我们就可以得到一个升序排序后的数组。

var sortColors = function(nums) {
    let index = 0
    for(let i = 0;i<nums.length;i++){
        if(nums[i]===0){
            [nums[i],nums[index]] = [nums[index],nums[i]]
            index+=1
        }
    }
    for(let i = index;i<nums.length;i++){
        if(nums[i]===1){
            [nums[i],nums[index]] = [nums[index],nums[i]]
            index+=1
        }
    }
    return nums
};

这种办法需要我们进行两次遍历,我们能不能只遍历一次呢,因为我们两次遍历是因为需要先排序0再排序1,那我们是不是可以同时排序0和2呢,采用双指针的方式,将0和2分别放到最前面后和最后面,那中间的不就是1了吗。但是在排序的过程中,我们还需要注意一点,因为我们将2和后指针交换了位置,那我们还需要将当前位减1避免跳过了对交换来的数字进行排序,又因为我们需要在判断到2的时候将当前位减1,那么我们需要将跳出位置设位后指针的位置以避免陷入死循环。

var sortColors = function(nums) {
    let startindex = 0
    let endIndex = nums.length-1
    for(let i = 0;i<=endIndex;i++){
        if(nums[i]===0){
            [nums[i],nums[startindex]] = [nums[startindex],nums[i]]
            startindex+=1
        }else if(nums[i]===2){
            [nums[i],nums[endIndex]] = [nums[endIndex],nums[i]]
            endIndex-=1
            i=i-1
        }
    }
    return nums
};