zoukankan      html  css  js  c++  java
  • July收集荷兰国旗问题之三路partition

    这道题目和分成两块的partition的扩展。比如有一堆0 1 2 数字组成的数组,要分成 00 00  11 1 1  222 2这样的顺序的。


    利用lumoto版的partition能够非常好的解决,比hoare好多了。并且直接利用loop invariant,变成i j k三个指针,[low,i]=0 [i+1,j]=1, [j+1,k-1]=2, 里面假设新来2的话,直接k++,

    假设是1的话,须要和a[j+1] swap, 同一时候j++, 假设0的话。须要先和a[i+1] swap i++, 然后和 a[j+1] swap j++, 因此算法例如以下:

    void NertherlandFlags(int *a, int n)
    {
    	int low=0,high=n-1;
    	int i=low-1,j=low-1;
    	for(int k=low;k<=high;k++)
    	{
    		if(a[k]==2) ;
    		else if(a[k]==1) 
    		{
    			j++;
    			swap(a[j],a[k]);
    		}
    		else if(a[k]==0)
    		{
    			i++;
    			swap(a[i],a[k]);
    			j++;
    			swap(a[j],a[k]);
    		}
    	}
    }
    代码比較好写,感觉这都是一类题,

    1.快排的partition。注意留一个pivot,算导是留最后一个,所以loop到high-1就停了,里面和pivot比。最后加一次swap把pivot放中间

    loop invariant:  [low,i] <pivot, [i+1, j-1]>pivot, =放那边都行。exit loop时 j=high, 最后把swap跳进来

    2.奇偶排序,整个区间划分为左奇右偶。和%2=0 =1比。loop 到high,
    loop invariant:  [low,i] 奇, [i+1, j-1]偶, exit时 j=high+1, 包括整个区间了

    3.荷兰国企问题,整个区间划分为0 1 2 (红 黄 蓝三块), loop 到high,

    loop invariant:  [low,i] 0, [i+1, j] 1, [j+1, k-1]  exit时 j=high+1, 包括整个区间了


    抱歉大家,这道荷兰国旗代码有bug。我才知道的。后经过分析主要是前面仅仅有2 或者0 2时,假设来了0,后面swap(a[j],a[k]) 会多交换一次使得交换回去,所以假设仅仅有0的情况。事实上不须要交换,而swap(a[j],a[k]) swap(a[j],a[k])都是子交换,因此1次两次不影响。于是统一到一起就是没有1区间的时候,也即[i+1,j]区间空,依据性质最多相差1。因此是i==j的时候出错,所以此时少一次swap, 可是i++ j++须要的 保持ij同步 

    事实证明未经过OJ測试的代码非常难保证正确性。leetcode setcolor题 就是上面的挂了,于是经过多种组合条件分析发现bug。单独处理1 interval空的情况

    void sortColors(int a[], int n) {
            int i=-1,j=-1;
            for(int k=0;k<=n-1;k++)
            {
                if(a[k]==0)
                {
                    if(i==j)//before are 2 or 0 2, swap one is only, two will error, also 0 swap once is ok, so that is no 1 interval would only swap once  
                    {
                        i++;
                        swap(a[i],a[k]);
                        j++;
                    }
                    else
                    {
                        i++;
                        swap(a[i],a[k]);
                        j++;
                        swap(a[j],a[k]);
                    }
                }
                else if(a[k]==1)
                {
                    j++;
                    swap(a[j],a[k]);
                }
            }
        }


    附上July版本号,前面 0 1区间 最后面2区间  1 2 之间没处理的


    void sortColors(int a[], int n) {
            int begin=0,end=n-1,current=0;
            while(current<=end)
            {
                if(a[current]==0)
    		        swap(a[begin],a[current]),begin++, current++;
    	        else if(a[current]==1)
    		        current++;
    	        else if(a[current]==2)
    		        swap(a[current],a[end]),end--; //current not move
            }
        }
    这样的不用考虑特殊情况。比方 仅仅有2 和仅仅有0 2的区间的情况,事实上也是单向扫描过来的,仅仅是调整了未处理部分和 0 1 2 区间的顺序而已,由于指针从current+1, 到end处理了。一个

    指针扫描的,还是单向扫描好。事实上也不是Hoart版啦,所以自己不用管Hoard版,坚持Lumoto版就能够了,sumous_t大神似乎也是的。


    似乎另一种改进第一个版本号的思路。就是不swap,而是覆盖,像优化partition一样的

    附上July博客 https://github.com/bolpigo/The-Art-Of-Programming-By-July/blob/master/ebook/zh/02.07.md

    sumous_t 大神代码: https://github.com/julycoding/The-Art-Of-Programming-By-July/blob/master/ebook/code/python/2.8:%20%E8%8D%B7%E5%85%B0%E5%9B%BD%E6%97%97%E9%97%AE%E9%A2%98.py


    再附上sumous_t大神帮我改动后AC的代码,膜拜下大神,还是女博士哦:)

    void sortColors(int a[], int n) {
            int low=0,high=n-1;  
        int i=low-1,j=low-1;  
        for(int k=low;k<=high;k++)  
        {  
            if(a[k]==2) ;  
            else if(a[k]==1)   
            {  
                j++;  
                swap(a[j],a[k]);  
            }  
            else if(a[k]==0)  
            {  
    			
    	    i++;j++;swap(a[j],a[k]);swap(a[j],a[i]);
    
            }  
        }


  • 相关阅读:
    CSS概述
    CSS基础
    CSS定位与布局
    CSS动画,2D和3D模块
    第一硬汉左宗棠死了,晚清再无脊梁!
    南怀瑾老师:读书万卷,神交古人
    左宗棠读书修身8句,神交古人
    神交古人
    心忧天下,神交古人
    ECCV 2016 paper list
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/5282077.html
Copyright © 2011-2022 走看看