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;

    }

}

 

你可能感兴趣的:(包)