Java数组 - 消除中间连续数

时间:2015-03-03 21:18:53

标签: java arrays algorithm

我想写一个算法,它几乎用一个整数的整数数组来完成:

1){8,9,10,14,15,16,19,20,21} - > {8,10,14,16,19,21}

2){8,9,10,11,12,14,15,16,18,19,20,21} - > {8,12,14,16,18,21}

我已经提出了这个算法:

int l=x.length;    
        for(int k=0;k<l-1;k++)
        {
            if (x[k]+1==x[k+1] && x[k]+2==x[k+2])
            {
                for(int z=k+1;z<l;z++)
                {
                    if(z+1==l)
                        x[z]=0;
                    else
                    x[z]=x[z+1];
                }                
                l--;
            }
        }

这个算法适用于上面提到的第一个例子但是如果我改为输入超过3个连续数字,它会搞砸结果,例如:

{8,9,10,11,12,14,15,16,18,19,20,21} - &gt; {8,10,12,14,16,18,20,21}代替{8,12,14,16,18,21}

我做错了什么?如何更改算法以成功消除所有中间连续数

3 个答案:

答案 0 :(得分:3)

当你在数组中找到3个连续数字(让我们说x[k]x[k+1]x[k+2]时,你将每个数字移到左边,丢弃中间的数字。因此,x[k+1]变成了x[k+2]。你剩下的不再是连续的数字了(因为x[k] + 2 == x[k+2]),所以不管x[k+3]是什么,你要保持x[k+2]左右(这是你的第二个例子中发生的事情,其中​​剩下10个)。

罪魁祸首是这一行:if (x[k]+1==x[k+1] && x[k]+2==x[k+2])。这条线实际上并没有说出你想说的话。它只匹配3个连续的数字,但你想要匹配更多。实际上,您希望匹配尽可能多的连续数字。一种方法是使用while循环:当数字是连续的时,继续搜索直到它结束(或者你到达数组的末尾)。一旦它结束,你就可以移动阵列的剩​​余部分,就像你一样,只移动一个而不是你找到的数字。

答案 1 :(得分:1)

@Tunaki是对的。

我会按照以下方式做点什么:

public static int[] filterImmediary(int[] x) {

    /*
     * Construct a boolean array that will be used to indicate whether the
     * corresponding element in the int array is an immediary consecutive
     * number.
     */
    int l = x.length;
    boolean[] rem = new boolean[l];
    int numKeeps = 0;

    /*
     * Fill boolean array
     */
    for (int k = 0; k < l - 1; k++) {
        int f = 1;
        while (k + f < l && x[k] + f == x[k + f]) {
            if (k + f + 1 < l && x[k] + f + 1 == x[k + f + 1]) {
                rem[k + f] = true;
            }
            f++;
        }
        if (!rem[k]) {
            numKeeps++;
        }
    }

    /*
     * Construct a new array with no immediary consecutive numbers to return
     * instead of mutating the original array.
     */
    int[] newX = new int[numKeeps+1];
    int i = 0;
    for (int k = 0; k < l; k++) {
        if (!rem[k]) {
            newX[i] = x[k];
            i++;
        }
    }
    return newX;
}

答案 2 :(得分:0)

@Tunaki给出了原因,这是一个评论解决方案:

public static void compactIt(int[] x) {
    int l = x.length;    
    int k = 0;
    while (k < l-1) {
        // find end of sequence of consecutive numbers
        int endSeq = k;
        while (endSeq < l-1 && x[endSeq]+1 == x[endSeq+1]) {
            endSeq++;
        }
        // how many numbers we have to compact?
        int numToSkip = endSeq - k - 1;
        if (numToSkip == -1) {
            // following number is not consecutive, just move to it
            k++;
        }
        else if (numToSkip == 0) {
            // there is only one consecutive number, keep both, move of 2
            k += 2;
        }
        else { 
            // there is at least 3 numbers in the sequence, 
            // copy numbers from the last in sequence to the end
            for (int z = k+1; (z+numToSkip) < l; z++) {
                x[z] = x[z+numToSkip];
            }
            // set ending slots to 0
            for (int z = l-numToSkip; z < l; z++) {
                x[z] = 0;
            }
            l = l-numToSkip;
            k += 2;
        }
    }
}

public static void main(String[] args) {
    int[] x = {1, 2, 3, 4, 10, 11, 20, 30, 31, 32, 33, 34, 40};
    compactIt(x);
    System.out.println(Arrays.toString(x));
}

打印:[1, 4, 10, 11, 20, 30, 34, 40, 0, 0, 0, 0, 0]