【问题标题】:Remove elements from HashSet on iteration迭代时从 HashSet 中删除元素
【发布时间】:2015-06-30 11:39:24
【问题描述】:

假设我有一个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。另一种方法是使用迭代器,但它会删除当前元素并且不将任何其他元素作为参数。我还能用什么?

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

【问题讨论】:

  • 将 sum-num 添加到一个新集合 (hs2) 中并在最后执行 hs.removeAll(hs2)?
  • 我知道这种方法。试图找到更优化的东西。另外,我只想删除 for 循环中的元素,这样我什至不会遍历该元素。
  • ConcurrentHashMap 创建一个Set 可能吗?这可能有点矫枉过正,但会根据您的需要/需要工作。
  • 如果你的总和是 6 并且你有数字 1 和 5,你怎么知道是去掉 1 还是 5?
  • 我是。迭代哈希集。如果我首先遇到 1,我将删除另一个,即 5。我这样做是因为最后我打印了所有总和为 6 的数字对。如果我不删除 5,我得到的结果为 1, 5 和 5,1。为了消除这种重复,如果 1 已经迭代,我想停止迭代 5。

标签: java algorithm hashset concurrentmodification


【解决方案1】:

保存一组你找到的数字。

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

从一个空的运行集开始,遍历你的数字集。对于您迭代的每个元素,如果它的 sum-compliment 在集合中,则将其从迭代器中删除。否则,将其添加到运行集中。

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,并且两个HashSets 将在代码块的末尾包含相同的内容。在这种情况下,最好只使用代码末尾的running 集合而不修改原始代码。这将使这段代码更加灵活和可重用。

【讨论】:

  • 不,第一个数字将保留,因为它的恭维不在运行集中。第二个数字将被删除,因为第一个数字在运行集中。
  • 哦,当然。 +1。您应该提到,此方法对原始 HashSet 具有破坏性,并且两个 HashSets 在循环结束时将相同(删除元素)。
  • 我知道这种技术,但我不想仅仅出于空间考虑而使用额外的 HashSet。不过还是谢谢。
  • 我认为您很难找到满足您所有考虑的解决方案。如果一次性和一套都是要求,那恐怕没有办法了。
【解决方案2】:

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

它比套装运行得更快!

【讨论】:

  • 10000 年前的溶液
猜你喜欢
  • 2010-11-09
  • 1970-01-01
  • 2020-06-09
  • 2012-05-13
  • 2011-02-21
相关资源
最近更新 更多