一、题目
二、文字解释
1.1 前言
本题是经典的「荷兰国旗问题」,由计算机科学家 Edsger W. Dijkstra 首先提出。如同图中所示的荷兰国旗,其由红、白、蓝三色水平排列组成。在算法领域,该问题可类比为将一个由特定的三种元素(可抽象对应红、白、蓝)组成的数组,通过特定算法实现元素的有序排列,使得相同元素相邻,且按照类似荷兰国旗颜色顺序的规则分布。

1.2 三指针算法实现
Java 代码实现
public class Solution {public void sortColors(int[] nums) {int low = 0;int mid = 0;int high = nums.length - 1;while (mid <= high) {if (nums[mid] == 0) {// 交换 nums[low] 和 nums[mid]int temp = nums[low];nums[low] = nums[mid];nums[mid] = temp;low++;mid++;} else if (nums[mid] == 1) {mid++;} else { // nums[mid] == 2// 交换 nums[mid] 和 nums[high]int temp = nums[mid];nums[mid] = nums[high];nums[high] = temp;high--;}}}
}1.3 实现细节
- 三指针定义: - low:指向 0 元素的右边界,区间- [0, low-1]中所有元素均为 0。
- mid:当前遍历的指针,负责检查并处理每个元素。
- high:指向 2 元素的左边界,区间- [high+1, n-1]中所有元素均为 2。
 
- 交换逻辑: - 当 nums[mid] == 0时:- 将 nums[low]和nums[mid]交换,然后low++和mid++。
- 这确保了所有 0 都被移动到数组左侧。
 
- 将 
- 当 nums[mid] == 1时:- 无需交换,直接 mid++,因为 1 应该保持在中间位置。
 
- 无需交换,直接 
- 当 nums[mid] == 2时:- 将 nums[mid]和nums[high]交换,然后high--。
- 注意此时 mid不移动,因为交换后的元素需要重新检查。
 
- 将 
 
- 当 
- 循环条件: - mid <= high,确保遍历到所有未处理的元素。
- 当 mid > high时,所有元素都已完成归类。
 
1.4 运行过程(以 [2,0,2,1,1,0] 为例)
 
- 初始状态:low=0, mid=0, high=5,数组:[2,0,2,1,1,0]
- nums[mid]=2:执行交换操作,- nums[0]与- nums[5]交换- 交换后数组:[0,0,2,1,1,2],high=4
 
- 交换后数组:
- nums[mid]=0:执行交换操作,- nums[0]与- nums[0]交换(实际不变)- 数组保持:[0,0,2,1,1,2],low=1, mid=1
 
- 数组保持:
- nums[mid]=0:执行交换操作,- nums[1]与- nums[1]交换(实际不变)- 数组保持:[0,0,2,1,1,2],low=2, mid=2
 
- 数组保持:
- nums[mid]=2:执行交换操作,- nums[2]与- nums[4]交换- 交换后数组:[0,0,1,1,2,2],high=3
 
- 交换后数组:
- nums[mid]=1:执行- mid++- 数组保持:[0,0,1,1,2,2],mid=3
 
- 数组保持:
- nums[mid]=1:执行- mid++- 数组保持:[0,0,1,1,2,2],mid=4
 
- 数组保持:
- 此时 mid=4 > high=3,算法终止。
1.5 时间与空间复杂度
- 时间复杂度:O(n) - 算法只需对数组进行一次遍历,每个元素最多被交换一次。
- 所有操作都是常数时间的简单比较和交换。
 
- 空间复杂度:O(1) - 算法只使用了三个指针变量和一个临时变量进行交换。
- 属于原地排序算法,不需要额外的空间。
 
要是对三指针算法不熟悉的可以去看我的三指针算法讲解
 【算法基础】三指针排序算法 - JAVA
