75. 颜色分类

题目

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

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

必须在不使用库内置的 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]012

思路

借用了外部空间解决,次一档的做法。

class Solution {
    public void sortColors(int[] nums) {
        // 左指针记录0要补充的位置,右指针记录2要补充的位置
        int i = 0, j = nums.length - 1;
        int[] ans = new int[nums.length];
        for (int index = 0; index < nums.length; index++) {
            if (nums[index] == 0) {
                ans[i++] = nums[index];
            } else if (nums[index] == 2) {
                ans[j--] = nums[index];
            }
        }
        while (i <= j) {
            ans[i++] = 1;
        }
        System.arraycopy(ans, 0, nums, 0, nums.length);
    }
}

但还有另一个不借助外部空间、且只需要O(1)的方法,75. 颜色分类 - O(n) 插入排序,简洁写法

需要借助一个O(1)插入元素的方法,虽然是别人的,但在我这里自己总结归纳一下

[0,0,1,1,2,2]为例,向其中插入一个0,并且保持有序,要怎么做?

直觉上,当然是在最后一位0之后插入,然后后面的元素依次向后挪一位。

但如果我们仔细观察,会发现其实只有3个元素需要改变,分别是下图中绿色圈的这3个元素

画板

所以可以看出,重复的元素中间部分是不需要改变的,只有首尾会变。由此,我们可以用三个变量分别记录每个元素结束的下一位指针,比如P0是元素0结束的下一位指针。

再插入0时,只需要把P0改成0,P1改成1,P3加上2即可。

有个特殊的逻辑处理,就是当元素如果只有0和1时,最后一步补2就不对了。但是也不需要用ifelse处理特殊情况,这里的逻辑都是把元素末尾加上了一个自身元素,所以我们可以把P2加上2之后,继续把P1改成1,P0改成0,这样子,如果只有0和1,就会覆盖P2的结果。

public void sortColors(int[] nums) {
        int p0 = 0, p1 = 0;
        for (int index = 0; index < nums.length; index++) {
            int num = nums[index];
            nums[index] = 2;// p2赋值2
            if (num <= 1) {
                nums[p1++] = 1;// p1赋值1
            }
            if (num == 0) {
                nums[p0++]=0;// p0赋值0
            }
        }
    }
posted @ 2025-08-12 22:23  恒星同学  阅读(4)  评论(0)    收藏  举报