计算含重复元素的两个List的差集(精确匹配重复次数)
解决方案:按次数移除List中匹配的元素
嘿,这个需求我太熟了——要从list1里精准移除list2中出现的元素,而且移除次数和list2里对应元素的出现次数完全一致对吧?咱们来看看两种实用的实现方式:
方法一:基于频率统计的高效实现(适合大数据量)
这种方法用Map统计list2里每个元素的出现次数,遍历list1时精准控制移除次数,效率很高,时间复杂度是O(n+m),适合处理大列表。
代码示例:
import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; public class ListRemoveByCount { public static void main(String[] args) { List<Integer> list1 = new ArrayList<>(Arrays.asList(1, 2, 2)); List<Integer> list2 = new ArrayList<>(Arrays.asList(2, 3, 4)); // 第一步:统计list2中每个元素的出现次数 Map<Integer, Integer> elementFrequency = new HashMap<>(); for (Integer num : list2) { // 用getOrDefault简化计数逻辑,不存在就默认0,然后加1 elementFrequency.put(num, elementFrequency.getOrDefault(num, 0) + 1); } // 第二步:遍历list1,按次数移除元素 // 这里必须用迭代器,不然遍历的时候删除元素会抛ConcurrentModificationException Iterator<Integer> iterator = list1.iterator(); while (iterator.hasNext()) { Integer currentNum = iterator.next(); // 检查当前元素在list2中还有剩余需要移除的次数 if (elementFrequency.containsKey(currentNum) && elementFrequency.get(currentNum) > 0) { iterator.remove(); // 把该元素的剩余移除次数减1 elementFrequency.put(currentNum, elementFrequency.get(currentNum) - 1); } } System.out.println(list1); // 输出结果:[1, 2] } }
思路解释:
- 先把list2里的元素和出现次数存在Map里,这样能快速查询每个元素需要移除多少次。
- 用迭代器遍历list1,普通for循环遍历删除元素会触发并发修改异常,迭代器的
remove()方法是安全的。 - 每移除一个匹配元素,就把Map里对应的计数减1,直到计数为0就不再移除该元素。
方法二:简洁遍历实现(适合小数据量)
如果你的列表数据量不大,这种方法更简洁直观——直接遍历list2的每个元素,从list1里移除第一个匹配的元素,刚好对应list2里的出现次数。
代码示例:
import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class SimpleListRemove { public static void main(String[] args) { List<Integer> list1 = new ArrayList<>(Arrays.asList(1, 2, 2)); List<Integer> list2 = new ArrayList<>(Arrays.asList(2, 3, 4)); // 遍历list2的每个元素,每次从list1移除第一个匹配项 // 遍历list2的副本是为了避免后续修改list2时出现意外,直接遍历list2也可以 for (Integer num : new ArrayList<>(list2)) { list1.remove(num); } System.out.println(list1); // 输出结果:[1, 2] } }
思路解释:
list1.remove(num)方法会移除list1中第一个匹配的元素,所以list2里有几个相同元素,就会从list1里移除几次,完全符合需求。比如如果list2是[2,2],那list1里的两个2都会被移除,结果就是[1]。- 这种方法的缺点是时间复杂度较高(每次
remove()都是O(n)),但小列表完全够用,代码也更短。
内容的提问来源于stack exchange,提问作者Holipop
相关产品推荐
相关产品推荐

