2 回答
TA贡献2039条经验 获得超7个赞
更新:由于我们只能使用 LinkedHashMaps ...
...并且列表可以有重复项:
创建一个
ListEntry
类,该类具有该数字在列表中重复的总次数和计数。所以如果 2 出现两次,我们将new ListEntry(number: 2, count: 2);
在 LinkedHashMap (LHM) 中创建一个;ListEntry
使用第一个列表中的数字填充对象的 LHM ;现在,遍历第二个列表,一一查看其数字:
如果未找到第二个列表的编号,则继续下一个编号;
对于找到的每个数字,将其在 LHM 中的条目放在最前面,将其“已见”计数存储在哈希映射 (
numberSeen
) 中,并更新另一个计数器 (intersectionCount
),用于跟踪迄今为止看到的总相交数;完成第二个列表的迭代后,LHM 前面有相交的数字;
现在,它是微不足道的使用
numberSeen
和intersectionCount
创造你的最终名单。
运行时复杂度再次为 O(m + n),空间复杂度为 O(n)。
原回复:
假设第一个列表的大小为n,第二个列表的大小为m,这是一个简单直接的解决方案,适用于 O(m + n) 时间和 O(m + n) 空间。
取第二个列表并将其所有元素放在映射
Integer
到的哈希映射中Integer
。这是为了跟踪列表中的重复项。如果列表中没有重复项,只需使用散列集;现在迭代第一个列表和列表中的每个元素:
如果该元素存在于映射中并且计数为正,则将此元素放入新列表中并减少其在映射中的计数;
如果该元素在地图中不存在或计数为 0,则跳至列表中的下一个元素。
最后,您的新列表将包含两个列表的交集,按照它们在第一个列表中出现的顺序。
总空间 = m 用于哈希图 + n 用于新列表。
总时间 = m 用于将元素放入哈希映射 + n 用于迭代第一个列表。
因此,O(m + n) 时间和 O(m + n) 空间。
TA贡献1830条经验 获得超3个赞
怎么样:
LinkedHashSet<Integer> intersection = new LinkedHashSet<>(A).retainAll(new HashSet<>(B));
或者在 a 中获取输出List:
List<Integer> intersection = new ArrayList<> (new LinkedHashSet<>(A).retainAll(new HashSet<>(B)));
实际上,这样做可能就足够了:
List<Integer> intersection = new ArrayList<> (A).retainAll(new HashSet<>(B));
由于执行了传递的retainAll调用,所以我们只需要转换为a就有恒定的搜索时间。containsCollectionBHashSet
编辑:
要将您建议的解决方案转换为线性时间解决方案,您应该利用HashSet查找时间:
public static List Intersection(List<Integer> A, List<Integer> B)
{
List<Integer> outcome = new ArrayList<>();
Set<Integer> BHashSet = new HashSet<>(B);
for(Integer Aitem : A) {
if(BHashSet.contains(Aitem)) {
outcome.add(Aitem);
}
}
return outcome;
}
添加回答
举报