「这是我参与2022首次更文挑战的第12天,活动详情查看:2022首次更文挑战」。
题目
给定一个包含红色、白色和蓝色、共 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
题解
思路
left为数字0的右开边界,right为数字2的左开边界。
00001102001112222
l r
- 当把 i 交换到左边界的时候:i 可以直接 +1 推进,因为左边不会有数字 2 了。
- 当把 i 交换到右边界的时候:可能会把数字 2 或者数字 0 置换 i 位置上,所以我们不能推进 i。
如果你还是对 i 的变化感到迷惑,那么下面是更加详细的解释:
i 位置上的数字代表着我们当前需要处理的数字。当 i 为数字 1 的时候,我们什么都不需要做,直接 +1 即可。如果是 0,我们放到左边,如果是 2,放到右边。
right 指针上的数字交换到 i 位置上以后,我们还需要对该数字进行处理。这个数字是一个全新的(0, 1, 2 都有可能),没有处理过的数字。
如果交换过来数字 0 或者数字 2 了,我们推进了 i 的话,那么就会出错。
而需要交换 i 位置数字到 left 上时,那么 i 位置上的数字一定是 0。我们可以分成两种情况来讨论:
- left 和 i 和重合:那么就相当于 i 和 i 自己交换,此时 i 位置上的数字就处理完了,i 和 left 都可以推进。
- i 和 left 不重合:那么 left 对应的数字一定是 1,如果不是 1 的话,left 和 i 一定是重合的(包含一种特殊情况,数组中只有 0 和 2 的时候)。此时交换完以后,i 位置上就会是 1,那么也可以直接 +1 推进。
代码
class Solution {
public void sortColors(int[] nums) {
int left=0,right=nums.length-1;
int i=0;
while(i<=right){
if(nums[i]==0)
swap(nums,i++,left++);
else if(nums[i]==2)
swap(nums,i,right--);
else
i++;
}
}
private void swap(int[] nums,int i,int j){
int temp=nums[i];
nums[i]=nums[j];
nums[j]=temp;
}
}
结语
业精于勤,荒于嬉;行成于思,毁于随。