为什么循环制动比它应该的早?

Why does for loop brake earlier than it should?

所以我有一个看起来像这样的 for 循环:

for (int i = 0; i < al.size(); i++) {
    for (int j = i + 1; j < al.size(); j++) {
        if (isAnagram(al.get(i), al.get(j))) {
            al.set(i, al.get(i) + " " + al.get(j));
            al.remove(j);
        }
    }
}

al 是其中包含单词(字符串)的 ArrayList,假设它看起来像这样:

[aabb, aabc, abab, abba, abcd, bbaa, cbad]

isAnagram returns truefalse 如果两个给定的字符串是否是变位词。 我试图让它将每个单词的所有字谜添加到一个字符串中,所以它看起来像这样:

[aabb abab abba bbaa, aabc, abcd cbad]

现在我得到:

[aabb abab, aabc, abba bbaa, abcd cbad]

所以我认为正在发生的事情 - 第二个 for 在找到 al.get(i) 的第一个变位词时结束,然后中断并继续下一个 i。有人可以解释为什么会这样吗?

您的列表:

[aabb, aabc, abab, abba, abcd, bbaa, cbad]

j=2 时,您将看到 abab。你发现它是一个字谜,所以你修改了前面的元素并删除了 abab。这是您的列表现在的样子:

[aabb abab, aabc, abba, abcd, bbaa, cbad]

现在有2个问题。首先,"abba"以前是al.get(3),现在是al.get(2)。但是当你循环回来时,你递增 j,所以 j 现在是 3。结果是你的代码永远不会查看 "abba".

另一个问题是,即使您的代码确实查看了 "abba",也不会发现它是一个变位词。这是因为您已经破坏了与之比较的字符串,即 al.get(i) 其中 i==0。这个字符串是 "aabb",但现在是 "aabb abab"。所以你的逻辑将不再有效。

您需要做两件事:

(1) 重新安排循环,以便在删除元素时不会增加 j;只有当你不删除它时,你才增加 j 。就个人而言,我会使用 while 循环而不是 for 循环来完成此操作。 [无论如何,我不喜欢修改您在 for 循环中使用的索引变量的做法;我认为这会使代码的可读性降低,因为对我来说通常的 for 循环与 j++ 作为第三部分看起来你要为序列中的每个整数执行正文,并修改 j 在循环的中间与外观相矛盾。不过其他人认为没问题。]

(2) 不要修改 al.get(i)(即不要调用 al.set(i,new value)),直到您不再需要它进行字谜检查,即当内部循环完成时。您必须声明一个变量来保存新字符串,然后稍后调用 al.set