增加迭代变量背后的直觉?
Intuition behind incrementing the iteration variable?
我正在解决一个关于 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++;
}
}
}
我的问题是,为什么i
在A[i]==0
和A[i]==1
时递增而不是在A[i]==2
时递增? 使用笔和纸,算法只是给我答案;但是你能提供一些直觉吗?
谢谢!
这将逐步遍历数组并保持元素0..i
排序的约束,并且所有元素都0
或1
。(那里的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 项,尚未查看。
更具体地说:在此特定示例中,仅处理三种不同的状态:
- 当前正在审查的项目等于 0:在这种情况下,此排序算法只是将该项目放在所有已排序的零的末尾(又名 A[low](。此外,之前处于 A[low] 的项目只能是 0 或 1(因为它们已经排序(,这意味着您可以与当前项目交换而不会破坏序列。现在有趣的部分:到目前为止,从 A[0] 到 A[low] 到 A[i] 的每个项目都已经排序,所以下一个必须审查的项目将是 A[i + 1],因此 i++
- 当前项等于 1:在这种情况下,无需进行交换,因为所有 0 和 1 都已经放在 A[0] 到 A[i - 1] 中,并且所有 2 都已经放在数组的末尾。这意味着,下一个要审查的项目是 A[i + 1],因此 i++ 当前项
- 等于 2:在这种情况下,当前项将放在数组的末尾,靠近(即左侧(所有其他已排序的 2 (A[high](。将从 A[high] 交换到 A[i] 的项目尚未排序,因此必须在下一步中审查,因此 i = i;
- "std::unique_XXX"命名约定背后的基本原理是什么?
- 共享指针和具有自定义删除程序的唯一指针之间的语法差异背后的任何原因
- 为什么理解这个递归示例如此难以转化为直觉?
- std::背后的基本原理assignable_from可能的实现
- 传递背后的原因 通过引用C++中的函数?
- 无法理解代码背后的逻辑,这是在两个给定数字之间生成素数的优化问题
- 嵌套循环背后的逻辑
- std::set<Key,Compare,Allocator>::find() 函数使用"<"运算符而不是"=="运算符背后的直觉是什么?
- while(sline >> n >> c && c== ',')背后的逻辑是什么?
- 全局和局部变量初始化与 constexpr 的差异背后的基本原理
- C++模板模板参数背后的基本原理
- C++活动异常机制背后的推理
- 此解决方案背后的直觉
- 增加迭代变量背后的直觉?
- 存储剩余部分背后的直觉?
- 使用单调堆栈背后的直觉
- 将其建模为BFS背后的直觉
- 这个DP的基本案例背后的直觉
- 动态编程中这种初始化背后的直觉
- 基本案例背后的直觉用于计算步骤数