我想写一个算法,它几乎用一个整数的整数数组来完成:
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}
我做错了什么?如何更改算法以成功消除所有中间连续数
答案 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]