颜色分类
题目:给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
注意:
不能使用代码库中的排序函数来解决这道题。
示例:
输入: [2,0,2,1,1,0]
输出: [0,0,1,1,2,2]
进阶:
一个直观的解决方案是使用计数排序的两趟扫描算法。
首先,迭代计算出0、1 和 2 元素的个数,然后按照0、1、2的排序,重写当前数组。
你能想出一个仅使用常数空间的一趟扫描算法吗?
解题思路
这道题我们结合三路快排的思想来解决。首先定义两个指针zero和two,其中zero指向数组头元素的前一个位置,two指向数组尾元素的最后一个位置。然后从数组头元素开始遍历。
- 当数组中的元素值为1时,直接跳过进行i++
- 当数组中的元素值为0时,zero++,让其指向数组第一个位置,然后进行交换,让数值为0的元素从数组最前开始往后放。最后进行i++,使其遍历下一个元素
- 当数组中的元素值为2时,two–,让其指向数组最后一个位置,然后进行交换,让数值为2的元素从数组最后开始往前放。(注意:这里不要进行i++,因为我们不知道和2交换后当前值为0还是1,如果为0时我们还得以当前值进入循环让其交换到数组的前半部分)
代码展示
代码如下:
class Solution {
public:
void sortColors(vector<int>& nums) {
int zero=-1;
int two=nums.size();
for(int i=0;i<two;)
{
if(nums[i]==1) i++;
else if(nums[i]==0)
{
zero++;
swap(nums[zero],nums[i]);
i++;
}
else
{
two--;
swap(nums[i],nums[two]);
}
}
return;
}
};
移动零
题目:
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
示例:
输入: [0,1,0,3,12]
输出: [1,3,12,0,0]
说明:
- 必须在原数组上操作,不能拷贝额外的数组。
- 尽量减少操作次数。
解题思路
首先题目说了不能借用其他数组,只能在原数组上面操作。所以我们可以先遍历数组,在遍历的过程中,将不为0 的元素从第一位开始往后放。当遍历完一次数组后,我们将后面剩下的元素直接全部赋值为0,这样就相当于把0全部滞后了。
代码展示
代码如下:
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int k=0;
for(int i=0;i<nums.size();i++)
{
if(nums[i]!=0)
{
nums[k++]=nums[i];
}
}
for(int j=k;j<nums.size();j++)
{
nums[j]=0;
}
}
};