你是如此接近:
我也建议不要使用list.length
而是elements
贯穿始终。否则,当val = 0
和列表包含0
时算法将中断。
public void removeAll(int val){
for(int n = 0; n <elements;n++){ // < -- change from list.length to elements
if(list[n] == val){
for (int j = n; j<elements-1;j++){ // < -- change from list.length to elements
list[j]=list[j+1];
}
list[elements-1]=0;
elements--;
n--; // <-- Add this line to not skip over the 'n + 1'th term
}
}
}
问题是,当您迭代集合时,您将在删除后跳过下一个词条。
例如,假设val = 2
和list = 1 2 2 3 4 4
:
算法识别和删除值:
1 2 2 3 4 4
^
在这之后你的阵列看起来像这一点,并要检查的下一个位置是n
现已增加了查看集合中的下一个项目。当我的示例中匹配删除标准的项目彼此相邻(相邻)时,不难看出这会造成问题。
1 2 3 4 4 0
^
为了弥补这一事件 - 你需要递减n
像这样n--;
当你遇到一个项目从集合中移除。这会使n
查看数组中相同的索引,直到该索引不再被要删除的项目(即符合相邻删除条件的项目)占据为止。
UPDATE
如果数组的计数不作为整个上限和val = 0
与包含至少一个0
数组会发生什么?
我会与主题保持一致,并举例说明问题。
让val = 0
和list = 1 2 0 3 4 4
。像往常一样,该算法识别并删除该值。
1 2 0 3 4 4
^
现在阵列看起来像这样:
1 2 3 4 4 0
^
然而,由于算法仍然在收集迭代,直到指数等于list.length
这仍然是价值6(它没有被递减状elements
)。该算法最终将在集合索引5处的伪项目处结束。这是麻烦开始的地方。
1 2 3 4 4 0
^
该指数将永远不会移动,因为总是将是另一个相邻0
因为我们将它们添加到集合的末尾,以表示未使用的索引!最终,你的收集将是这样的:
0 0 0 0 0 0
^
在下面的迭代 - IndexOutOfBoundsException
都是Java被抛出list[-1] = 0
会发生。
希望有帮助!
在目前的版本中,如果它们不相邻,它应该删除'val'的多个实例。问题是,当你删除第n个值时,你跳过了第n + 1个值,这已经成为第n个值。你最后两个(非大括号)行也会遇到问题,它们会在循环的每次迭代中运行,而不是仅仅在找到'val'时。将'if'改为'while',将'}'改为两行将是一个好的开始,但不是一个完整的解决方案。 –
非常感谢你,你只是救了我我的计算机科学成绩:) – user3277923
我会推荐使用'elements'变量而不是'list.length',因为算法会在val = 0上破坏,并且列表包含一个' 0'。 –