我在LeetCode.com上解决了一个问题:
给定一个n对象为红色,白色或蓝色的数组,将它们就地排序,使相同颜色的对象相邻,颜色顺序为红色,白色和蓝色。这里,他们使用整数0,1和2分别表示红色,白色和蓝色。 [无法使用琐碎的计数排序]。
输入:[2,0,2,1,1,0];预期的输出是:[0,0,1,1,2,2]。
其中一个highly upvoted solutions是这样的:
public void sortColors(vector<int>& A) {
if(A.empty() || A.size()<2) return;
int low = 0;
int high = A.size()-1;
for(int i = low; i<=high;) {
if(A[i]==0) {
// swap A[i] and A[low] and i,low both ++
int temp = A[i];
A[i] = A[low];
A[low]=temp;
i++;low++;
}else if(A[i]==2) {
//swap A[i] and A[high] and high--;
int temp = A[i];
A[i] = A[high];
A[high]=temp;
high--;
}else {
i++;
}
}
}
我的问题是,i
和A[i]==0
时为什么A[i]==1
会增加而A[i]==2
时呢?使用笔和纸,算法只是工作给我答案;但是你能提供一些直觉吗?
谢谢!
答案 0 :(得分:5)
此步骤遍历数组并维护元素0..i
已排序的约束,以及所有0
或1
。 (那里的2
被交换到数组的末尾。)
当A[i]==0
时,您将i
(我们刚才说的0
)的元素与low
处的元素进行交换,这是第一个1
- 0..i
范围内的元素(如果有)。因此,在交换之后,A[i]==1
即可(约束仍然有效)。我们现在可以安全地在阵列中前进。如果A[i]==1
最初也是如此,在这种情况下不执行交换。
当A[i]==2
时,你基本上将元素i
(我们刚才说的是2
)移动到数组的末尾。但是你也要从数组的末尾移动一些东西进入元素i
的位置,而我们也不知道那个元素是什么(因为我们还没有处理过之前,与A[i]==0
案例不同)。因此,我们无法安全地向前移动i
,因为A[i]
处的新元素可能尚未出现在正确的位置。我们需要另一个迭代来处理新的A[i]
。
答案 1 :(得分:2)
也就是说,因为对于0和1,只处理当前项目剩余的项目,并且已经审查/排序了这些项目。只处理来自阵列右端的2s项目,尚未查看。
更具体一点:在此特定示例中,仅处理三种不同的状态: