每日一题——颜色分类

105 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 6 天,点击查看活动详情


颜色分类

给定一个包含红色、白色和蓝色、共 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 处于 left 之后,并且 i 位置上的元素为零时,说明 i 位置上的元素需要更新,将其更换为 left 指针上的元素,将 left 后移一位,以保证 left 之前的元素均为红色;right 指针进行同样的处理,这样通过遍历一遍数组即可完成排序效果。

题解

class Solution {
    public void sortColors(int[] nums) {
        int left = 0, right = nums.length - 1;
        for(int i = 0; i <= right; i++) {
            if(nums[i] == 0 && i > left) {
                swap(nums, left++, i--);
            }else if(nums[i] == 2 && i < right) {
                swap(nums, right--, i--);
            }
        }
    }

    private void swap(int[] nums, int i, int j) {
        nums[i] ^= nums[j];
        nums[j] ^= nums[i];
        nums[i] ^= nums[j];
    }
}