2021年11月25日
给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
思路分析:打眼一看,中等难度,也不知道题目要干啥,但是看了示例就清楚了,这不就是一个简单的排序题,所以上手就是调一个Arrays.sort的API,但是这样做就没什么意思了。本题一共有三个方法解决。
方法一:调API,是人都会(一行代码秒中等题的感觉,但是面试如果遇到,小心被面试官打死)
代码和提交结果如下:
class Solution {
public void sortColors(int[] nums) {
Arrays.sort(nums);
}
}
方法二:单指针算法
算法思路:
我们可以使用一个指针指向数组的第一个位置,比如 int p = 0;先遍历一边数组,如果nums[i] == 0 ;就把nums[i] 与 nums[p] 的数互换位置,随后p++;因为要将数组按0,1,2的顺序排列,所以我们需要遍历扫描两遍数组,第一遍将所有的 0 换到数组的前面,然后 指针p 的位置刚好在最后一个 0 的后面,然后第二遍遍历数组,同样的办法将所有的 1 挪到 0 的后面。 图示如下图:
代码和提交截图如下:
class Solution {
public void sortColors(int[] nums) {
int p = 0;
for(int i = 0 ; i < nums.length ; i++){
if(nums[i] == 0 ){
int temp = nums[i];
nums[i] = nums[p];
nums[p] = temp;
p++;
}
}
for(int i = 0 ; i < nums.length ; i++){
if(nums[i] == 1){
int temp = nums[i];
nums[i] = nums[p];
nums[p] = temp;
p++;
}
}
}
}
方法三:双指针算法
算法思路:
上面一种算法我们使用了一个指针来进行移动和交换,所以导致每次只能换一个元素,所以我们可以考虑使用双指针,一次扫描便可以将数组完成排序。
我们可以事先定义好两个指针,p0 和 p2 然后一个指向数组的头部,一个指向数组的尾部,然后扫描数组,如果nums[i] == 0 ;则将nums[i] 与 nums[p0] 位置交换, 如果nums[i] == 2 ;则将nums[i] 与 nums[p2] 位置交换,如果是 nums[i] == 2 交换的前提条件是 i < p2,不然就换回去了,所以,并且交换完之后nums[i]的位置还有可能是 2 ,但是 i 已经过去了,所以我们需要用while(i < p2 && nums[i] == 2){交换;p2--};代码和提交结果如下图:
class Solution {
public void sortColors(int[] nums) {
int p1 = 0;
int p2 = nums.length - 1;
for(int i = 0 ; i < nums.length ; 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[p1];
nums[p1] = temp;
p1++;
}
}
}
}
总结:还是尽量不要用API,并且方法三的时候一定要注意后面的特殊情况,不然会出错。