2015-04-22 90 views
3

假設我有刪除元素HashSet從HashSet的迭代的

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

我想遍歷它以這樣的方式,對於給定的總和,說6,而迭代的元素,如果我在總和= 6的Set中找到2個元素,我想刪除另一個。 。E.克,如果我遍歷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。另一種方法是使用迭代器,但它將刪除當前元素,並且不會將任何其他元素作爲參數。我還能使用什麼?

更新:我知道使用額外的設置和所有的技術。如果可能的話,我只想要一個非常優化的解決方案,而不會增加時間和空間的複雜性。

+1

將sum-num添加到一個新的集合(hs2)中並在最後執行hs.removeAll(hs2)? –

+0

我知道這種方法。正試圖找到更優化的東西。此外,我只想刪除for循環中的元素,以便我甚至不遍歷該元素。 –

+1

從'ConcurrentHashMap'創建'Set'也許吧?這可能是矯枉過正,但會按照你的需要工作。 –

回答

3

保留一組正在運行的數字。

這將允許你有一個通過解決方案。

從一個空的運行集合開始,遍歷你的一組數字。對於迭代的每個元素,如果它的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,並且兩個HashSet旨意包含在代碼塊的端部相同的內容。在這種情況下,最好使用在代碼末尾設置的running,而不要修改原始內容。這將使這個代碼更加靈活和可重用。

+0

不,第一個號碼將保留,因爲它的恭維不在運行集合中。第二個號碼將被刪除,因爲第一個號碼在運行中。 –

+1

哦,當然。 +1。你應該提到這個方法對最初的'HashSet'是破壞性的,並且在循環結束時兩個'HashSet'都將是相同的(刪除這些元素)。 – durron597

+0

我知道這種技術,但我不想僅僅爲了空間考慮而使用額外的HashSet。不過謝謝。 –

2

您可以改用排序列表。 首先按升序排列數字。那麼你把2個迭代器放在第一個元素中,其他元素放在最後一個元素中。那麼在每一步中,如果迭代器下的2個項目的總和小於你想要的數量,你應該增加第一個迭代器,如果它的磨碎機你應該減少第二個迭代器,並且如果它等於你想要的,你選擇它們並首先增加並減少第二個迭代器。

它的工作速度比設定更快!

+0

10000歲的soln – Avi