递增迭代变量后的直觉?

时间:2018-05-11 20:03:48

标签: c++ algorithm

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

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

谢谢!

2 个答案:

答案 0 :(得分:5)

此步骤遍历数组并维护元素0..i已排序的约束,以及所有01。 (那里的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项目,尚未查看。

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

  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. 当前项目等于2:在这种情况下,当前项目将被放置在数组的末尾,旁边(即左侧)所有其他已经排序的2s(A [高])。该项目将从A [high]交换到A [i]尚未进行分类,因此必须在下一步中进行审核,因此我i = i;