在迭代中从 HashSet 中删除元素

Remove elements from HashSet on iteration

假设我有一个 HashSet:

[1, 2, 3, 4, 5, 6]

我想以这样的方式迭代它,对于给定的总和,比如 6,在迭代元素时,如果我在 Set 中找到 2 个元素总和 = 6,我想要删除另一个。例如,如果我迭代 1,我应该删除 5。我试图做这样的事情:

HashSet<Integer> hs = new HashSet(arr);
int sum = 6;
for(int num : hs) {
    if(hs.contains(sum - num)) {
        hs.remove(sum - num);
    }
}

显然它会抛出 java.util.ConcurrentModificationException。另一种方法是使用迭代器,但它会删除当前元素并且不会将任何其他元素作为参数。我还能用什么?

更新:我知道使用附加集和所有的技巧。我只是想要一个非常优化的解决方案,而不增加时间和 space 复杂性,如果可能的话。

保留你找到的一组 运行 个数字。

这将使您获得一次性解决方案。

从一个空的 运行 集开始,然后遍历您的数字集。对于您遍历的每个元素,如果其求和补语在集合中,则将其从迭代器中移除。否则,将其添加到 运行 集合。

HashSet<Integer> hs = new HashSet(arr);
HashSet<Integer> running = new HashSet();
int sum = 6;
Iterator<Integer> iter = hs.iterator();
while (iter.hasNext()) {
    int num = iter.next();
    if (running.contains(sum - num)) {
        iter.remove();
    } else {
        running.add(num);
    }
}

此代码将修改原始 HashSet,并且两个 HashSet 将在代码块末尾包含相同的内容。在这种情况下,最好只使用代码末尾设置的 running 而不要修改原始代码。这将使这段代码更加灵活和可重用。

您可以改用排序列表。 首先按递增顺序对数字进行排序。然后将 2 个迭代器放在第一个元素中,另一个放在最后一个元素中。然后在每个步骤中,如果迭代器下的 2 个项目的总和小于你想要的数量,你应该增加第一个迭代器,如果它的磨碎器你应该减少第二个迭代器,如果它等于你想要的你选择它们并首先增加并减少第二个迭代器。

效果比套装还快!