增加迭代变量背后的直觉?

Intuition behind incrementing the iteration variable?

本文关键字:直觉 背后 迭代 变量 增加      更新时间:2023-10-16

我正在解决一个关于 LeetCode.com 的问题:

给定一个包含 n 个颜色为红色、白色或蓝色对象的数组,对它们进行就地排序,以便相同颜色的对象相邻,颜色按红色、白色和蓝色的顺序排列。 在这里,他们使用整数 0、1 和 2 分别表示红色、白色和蓝色。 [不能使用琐碎的计数排序]。

对于输入:[2,0,2,1,1,0];预期的输出为:[0,0,1,1,2,2]。

其中一个备受好评的解决方案是这样的:

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++;
}
}
}

我的问题是,为什么iA[i]==0A[i]==1时递增而不是在A[i]==2时递增? 使用笔和纸,算法只是给我答案;但是你能提供一些直觉吗?

谢谢!

这将逐步遍历数组并保持元素0..i排序的约束,并且所有元素都01。(那里的2被交换到数组的末尾。

A[i]==0时,您将i处的元素(我们刚刚说是0(与low处的元素交换,这是0..i范围内的第一个1元素(如果有的话(。因此,在交换之后,A[i]==1哪个是可以的(约束仍然有效(。我们现在可以安全地在阵列中前进。如果最初A[i]==1也是如此,在这种情况下,不执行交换。

A[i]==2时,你实际上是将元素i(我们刚刚说是2(移动到数组的末尾。但是你也把一些东西从数组的末尾移动到元素i的位置,我们不知道那个元素是什么(因为我们以前没有处理过它,不像A[i]==0的情况(。因此,我们不能安全地向前推进i,因为A[i]的新元素可能还没有放在正确的位置。我们需要另一个迭代来处理新的A[i].

也就是说,因为对于 0 和 1,只处理当前项目剩余的项目,并且已经查看/排序的项目。仅处理数组右端的 2s 项,尚未查看。

更具体地说:在此特定示例中,仅处理三种不同的状态:

  1. 当前正在审查的项目等于 0:在这种情况下,此排序算法只是将该项目放在所有已排序的零的末尾(又名 A[low](。此外,之前处于 A[low] 的项目只能是 0 或 1(因为它们已经排序(,这意味着您可以与当前项目交换而不会破坏序列。现在有趣的部分:到目前为止,从 A[0] 到 A[low] 到 A[i] 的每个项目都已经排序,所以下一个必须审查的项目将是 A[i + 1],因此 i++
  2. 当前项等于 1:在这种情况下,无需进行交换,因为所有 0 和 1 都已经放在 A[0] 到 A[i - 1] 中,并且所有 2 都已经放在数组的末尾。这意味着,下一个要审查的项目是 A[i + 1],因此 i++
  3. 当前项
  4. 等于 2:在这种情况下,当前项将放在数组的末尾,靠近(即左侧(所有其他已排序的 2 (A[high](。将从 A[high] 交换到 A[i] 的项目尚未排序,因此必须在下一步中审查,因此 i = i;