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;
}
}

浙公网安备 33010602011771号