1、题目描述:(题目地址:LeetCode75 颜色分类):
给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

2、解题思路和Java代码:
这是一个经典的“荷兰旗”问题,由计算机科学家 Edsger W. Dijkstra 首先提出。欧洲很多国家的国旗都是三种颜色的不同分布、排列。

  • 方法一:单指针
    我们可以考虑对数组进行两次遍历。在第一次遍历中,我们将数组中所有的 0 交换到数组的头部。在第二次遍历中,我们将数组中所有的 1 交换到头部的 0 之后。此时,所有的 2 都出现在数组的尾部,这样我们就完成了排序。
class Solution {
   
    public void sortColors(int[] nums) {
   
        int n = nums.length;
        int ptr = 0;
        for (int i = 0; i < n; ++i) {
   
            if (nums[i] == 0) {
   
                int temp = nums[i];
                nums[i] = nums[ptr];
                nums[ptr] = temp;
                ++ptr;
            }
        }
        for (int i = ptr; i < n; ++i) {
   
            if (nums[i] == 1) {
   
                int temp = nums[i];
                nums[i] = nums[ptr];
                nums[ptr] = temp;
                ++ptr;
            }
        }
    }
}
  • 方法二:双指针(统计0和1)
    方法一需要进行两次遍历,那么我们是否可以仅使用一次遍历呢?我们可以额外使用一个指针,即使用两个指针分别用来交换 0 和 1。
class Solution {
   
    public void sortColors(int[] nums) {
   
        int n = nums.length;
        int p0 = 0, p1 = 0;
        for (int i = 0; i < n; ++i) {
   
            if (nums[i] == 1) {
   
                int temp = nums[i];
                nums[i] = nums[p1];
                nums[p1] = temp;
                ++p1;
            } else if (nums[i] == 0) {
   
                int temp = nums[i];
                nums[i] = nums[p0];
                nums[p0] = temp;
                if (p0 < p1) {
   
                    temp = nums[i];
                    nums[i] = nums[p1];
                    nums[p1] = temp;
                }
                ++p0;
                ++p1;
            }
        }
    }
}
  • 方法三:双指针之循环不变量(统计0和2)
    与方法二类似,我们也可以考虑使用指针 p0来交换 0,p2来交换 2。此时,p0的初始值的初始值仍然为 0,而 p2的初始值为 n-1。在遍历的过程中,我们需要找出所有的 0 交换至数组的头部,并且找出所有的 2 交换至数组的尾部。
class Solution {
   
    public void sortColors(int[] nums) {
   
        int n = nums.length;
        int p0 = 0, p2 = n - 1;
        for (int i = 0; i <= p2; ++i) {
   
            while (i <= p2 && nums[i] == 2) {
   
                int temp = nums[i];
                nums[i] = nums[p2];
                nums[p2] = temp;
                --p2;
            }
            if (nums[i] == 0) {
   
                int temp = nums[i];
                nums[i] = nums[p0];
                nums[p0] = temp;
                ++p0;
            }
        }
    }
}

部分内容参考leetcode官方解题思路:LeetCode解题思路