m个珠子共n种颜色,找出包含n种颜色的最短连续片段

原题目:

有一串的珠子(首尾不相连),共有m个,每一个珠子有一种颜色,并且颜色的总数不超过n(n<=10),求连续的珠子的颜色总数为n时,长度最小的区间。


题目分析:

一 、暴力搜索

    1、最简单的方法---暴力搜索,逐个扫描第i个位置开始包含n中颜色最短区间,时间复杂度为O(m^2) 。

    2、从i开始扫描,每出现一种新的颜色,计数+1 ,当计数=n时候,结束,此时即为i开始的最短区间 。

二 、

   1、扫描一遍数组m,计算出每种颜色在数组m中下一次出现的位置,存在数据nextColor[m]中 (每种颜色的最后一个元素的下一个位置记为-1 ,在后面的程序中需要特殊处理)。

   2、从0位置开始扫描数组m,找出第一个包含所有颜色的区间,此时的开始位置即为beginTag (此时是0),结束位置记为endTag 。

   3、对beginTag进行操作:如果beginTag位置的颜色的下一个颜色nextColor[beginTag]<=endTag ,则将beginTag++ ,重复此步骤,直到nextColor[beginTag]>endTag  或者 beginTag==endTag ,此时beginTag---->endTag即为以endTag结束但包含所有颜色的最小区间 。

    4、endTag后移一步,然后重复步骤3  。

    5、重复步骤4 ,直到endTag=m.length-1 。

     6、此时可以得到所有元素结尾的最短区间的长度,选取一个最小的 。

代码如下:

package ddc.test.com;

public class MNSelectTestMain {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int data[]={0,1,2,3,4,4,5,4,2,3,1,0,2,3};
        getSubAll(data,6);

    }
    public static int[] getSubAll(int[] colorArray,int colorLength){
        for(int color:colorArray){
            if(color>=colorLength)
                throw new RuntimeException("color error!!");
        }
        int[] least=new int[colorArray.length];
        
        int[] nextColor=new int[colorArray.length];
        for(int i=0;i<nextColor.length;i++)
            nextColor[i]= -1;
        int[] colorCounter=new int[colorLength];
        int[] colorTmp=new int[colorLength];
        for(int i=0;i<colorTmp.length;i++)
            colorTmp[i]= -1;
        
        for(int i=colorArray.length-1;i>=0;i--){
            nextColor[i]=colorTmp[colorArray[i]];
            colorTmp[colorArray[i]]=i;
        }
        int hasColor=0 ;  //已经发现的颜色总数
        int beginTag=0 ,endTag =0;
        //找到第一个包含所有颜色的结束点
        while(endTag <colorArray.length){
            if(colorCounter[colorArray[endTag]]==0){
                hasColor++;
                colorCounter[colorArray[endTag]]++;
            }
            if(hasColor==colorLength)
                break;
            endTag++;
        }
        //结束点逐步后移,然后找到以endTag为结束点的最短区间
        while(endTag<colorArray.length){
            if(nextColor[beginTag]>=0&&nextColor[beginTag]<=endTag){
                beginTag++;
                continue;
            }
            least[endTag]=endTag-beginTag+1;
            endTag++;
        }
        //打印
        for(int tt:least)
            System.out.print(tt+" ");
        System.out.println();
        for(int tt:colorArray)
            System.out.print(tt+" ");
        return colorArray;
    }
}

 

posted @ 2012-05-31 16:02  xiao晓  阅读(1388)  评论(0编辑  收藏  举报