解法:三指针
思路:用三个指针,把数组划分为三个区域:
for循环遍历数组,i遍历数组,left是0区间的末尾,right是2区间的开头,0 1 2区间成功被划分
而上面的图画是最终实现的图样,实际left,right的移动得配合nums[i]来:
left = -1,right = nums.size();
1.nums[i] == 0,要保证[0,left]为全0,left++,swap(nums[left],nums[i]) ,处理完当前nums[i],i++
合并为:swap(nums[++left],nums[i++]
2.nums[i] == 1, 要保证[left+1,i-1]是全1,所以 i++ 即可保证。
3.nums[i] == 2,要保证[right,n-1]是全2,right--,swap(nums[right,nums[i]),处理完当前nums[i],不用i++,因为此时swap过去的nums[rigjt] 这个数依旧还没判断呢,所以此时不能i++
nums[i] == 0的例子i++是因为俩交换的数都已经判断完了。
合并为:swap(nums[--right],nums[i])
注意:结束标志,当i遍历时,i == right的时候,证明已经排好序了,结束循环即可。
附上思路图:
完整代码:
class Solution {
public:
void sortColors(vector<int>& nums)
{
int n = nums.size(),l = -1,r = n;
for(int i = 0;i<n;)
{
if(nums[i] == 0)
swap(nums[++l],nums[i++]);
else if(nums[i] == 1)
i++;
else if(nums[i] == 2)
{
if(i == r) break;
swap(nums[--r],nums[i]);
}
}
}
};