98.颜色分类

给定一个包含红色、白色和蓝色、共 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] 为 0、1 或 2

代码:
1.两次遍历

class Solution {
    /**
     * 对包含0、1、2的数组进行原地排序(荷兰国旗问题)
     * 使用两次遍历的解法:
     * 1. 第一次遍历将所有0移到数组前端
     * 2. 第二次遍历将所有1移到0之后的位置
     * 
     * @param nums 待排序的数组,元素只能是0、1或2
     */
    public void sortColors(int[] nums) {
        int n = nums.length;
        //指向当前需要交换的位置
        int ptr = 0;
        //第一次遍历:将所有0移到数组前端
        for (int i = 0; i < n; ++i) {
            if (nums[i] == 0) {
                //交换当前元素和ptr位置的元素
                swap(nums,i,ptr);
                //移动指针,扩大0的区间
                ++ptr;
            }
        }
        //第二次遍历:将所有1移到0之后的位置
        for (int i = ptr; i < n; ++i) {
            if (nums[i] == 1) {
                //交换当前元素和ptr位置的元素
                swap(nums,i,ptr);
                //移动指针,扩大1的区间
                ++ptr;
            }
        }
    }
    //交换数组中两个位置的元素
    public void swap(int[] nums,int x,int y){
        int temp = nums[x];
        nums[x] = nums[y];
        nums[y] = temp; 
    }
}

2.一次遍历

class Solution {
    /**
     * 对包含0、1、2的数组进行原地排序(荷兰国旗问题)
     * 使用三指针法,一次遍历完成排序
     * 
     * 算法思想:
     * 1. p0指向0的右边界,p1指向1的右边界
     * 2. 遍历数组:
     *    - 遇到1:交换到p1位置,p1右移
     *    - 遇到0:先交换到p0位置,如果p0<p1说明把1换出去了,需要再交换回来
     *    - 遇到2:不做处理(会被后续交换覆盖)
     * 
     * @param nums 待排序的数组,元素只能是0、1或2
     */
    public void sortColors(int[] nums) {
        int n = nums.length;
        //p0:指向最后一个0的下一个位置(0的右边界)
        //p1:指向最后一个1的下一个位置(1的右边界)
        int p0 = 0, p1 = 0;
        for (int i = 0; i < n; ++i) {
            if (nums[i] == 1) {
                //当前元素是1,交换到p1位置
                swap(nums,i,p1);
                //扩展1的右边界
                ++p1;
            } else if (nums[i] == 0) {
                //当前元素是0,先交换到p0位置
                swap(nums,i,p0);
                //如果p0<p1,说明刚才把1交换出去了,需要再交换回来
                if (p0 < p1) swap(nums,i,p1);
                //两个指针都向右移动
                ++p0;
                ++p1;
            }
        }
        //元素2不做处理,会被后续交换覆盖
    }
    //交换数组中两个位置的元素
    public void swap(int[] nums,int x,int y){
        int temp = nums[x];
        nums[x] = nums[y];
        nums[y] = temp; 
    }
}
posted @ 2025-05-11 09:12  回忆、少年  阅读(15)  评论(0)    收藏  举报