为什么这个循环只适用于一次迭代?

时间:2015-08-23 00:00:39

标签: java arrays debugging

我有一个循环,用于删除输入数组中的所有零。我使用了数组:

[[0, 0, 2, 2, 3, 4],[[0, 0, 2, 2, 3, 4]]

这是用于删除“全零”的循环。

public static int[][] removeTrivialCases(int[][]array)
    int[][] correctedArray = array;

    for (int i = 0; i < correctedArray.length; i++) {
        for (int j = 0; j < correctedArray[i].length; j++) {
            if (correctedArray[i][j] == 0) {
                correctedArray[i] = ArrayUtils.removeElement(correctedArray[i], j);
            }
        }
    }
return correctedArray;

当输入上面的数组时,我只能得到这个:

[[0, 2, 2, 3, 4],[0, 2, 2, 3, 4]]

为什么这个循环只从数组中删除一组零?

注意: ArrayUtilsApacheLang library中的一个类。

2 个答案:

答案 0 :(得分:2)

使用整数索引遍历数组时,必须小心,同时从数组中删除元素。假设你的数组是[0,0,2,2,3,4]。您有一个for循环,例如for (i = 0; i < a.length(); i++)。当i为0时,您查找a.get(0),即0,然后删除该元素。这意味着数组现在是[0,2,2,3,4]。现在for循环将i增加到1.当您查找a.get(1)时会发生什么?移动数组中的元素会导致索引遗漏元素。

这个常见问题至少有几种解决方案。一种是设置一个新数组来保存结果,这样你就不会移动你循环的数组中的元素。 (对于大型数组,无论如何都会更有效,因为你没有多次移动相同的元素 - 你将有一个O(n)算法而不是O(n 2 )。)另一种方法是进行设置,以便仅在不删除元素时增加索引,例如

int i = 0;
while (i < a.length()) {
    look at a.get(i);
    ... see if you want to remove the element
    if (you want to remove the element) {
        call method to delete element from array;
    } else {
        i++;
    }
}

现在,由于只有在不删除元素时才增加i,所以不会跳过任何元素。

答案 1 :(得分:0)

你的问题是,当你在每次迭代中增加j时,你会在删除一个元素后跳过元素,因为数组会在每个删除操作中移动元素,你需要确保每个元素在移除时的位置它 所以你应该在每次删除元素后用正确的索引调整j 在您的代码[0, 0, 2, 2, 3, 4]中,当您从数组中删除元素[0][0]时,数组的大小将为5,而j的第一个索引将转移到左[0, 2, 2, 3, 4],所以当增加j您将跳过数组

中的第二个0元素

在每次删除元素减少j索引后,您可以通过这种方式更正代码:

 for (int i = 0; i < correctedArray.length; i++) {
        for (int j = 0; j < correctedArray[i].length; j++) {
            if (correctedArray[i][j] == 0) {
                correctedArray[i] = ArrayUtils.removeElement(correctedArray[i], j);
                j--;
            }
        }
     }

现在当你删除元素时,当你增加j索引时,你不会跳过下一个元素

我希望现在的想法很明确!