我有几个没有重复元素的ArrayLists。我想在每个arraylist中找到它们的交集并返回共同元素的索引
例如,如果我输入为{0,1,2},{3,0,4},{5,6,0}
,那么我想在这里返回{0},{1},{2}
,即公共元素0的索引。
我能想到的一种方法是在所有ArrayLists上使用连续retainAll()
来获取交集,然后使用indexOf()
为每个输入ArrayList查找交集元素的索引。
有没有更好的方法呢?
答案 0 :(得分:1)
首先对列表进行排序至少需要O(nlogn)
次。如果您正在寻找更高效的算法,可以使用哈希映射获得O(n)
。
例如
A=[0,1,2],B=[3,0,4],C=[5,6,0]
您可以循环遍历每个列表,并在元素上附加带有哈希的元素。最终的哈希看起来像
H = {0:[0,1,2], 1:[1], 2:[2], 3:[0], 4:[2], 5:[0], 6:[1]}
这里,键是元素,值是它对应列表中的索引。现在,只需循环遍历hashmap,找到大小为3的任何列表,在这种情况下,获取索引。
代码看起来像这样(未经测试):
int[][] lists = {{0,1,2}, {3,0,4}, {5,6,0}};
// Create the hashmap
Map<Integer, List<Integer>> H = new HashMap<Integer, List<Integer>>();
for(int i = 0; i < lists.length; i++){
for(int j = 0; j < lists[0].length; j++){
// create the list if this is the first occurance
if(!H.containsKey(lists[i][j]))
H.put(lists[i][j], new ArrayList<Integer>());
// add the index to the list
H.get(lists[i][j]).add(j);
}
}
// Print out indexes for elements that are shared between all lists
for(Map.Entry<Integer, List<Integer>> e : H.entrySet()){
// check that the list of indexes matches the # of lists
if(e.getValue().size() == lists.length){
System.out.println(e.getKey() + ":" + e.getValue());
}
}
编辑:刚刚注意到你建议在你的问题中使用retainAll()。那也是O(n)。
答案 1 :(得分:0)
这是一个非常低效但相当可读的解决方案,使用流返回列表列表。
int source[][];
Arrays.stream(source)
.map(list -> IntMap.range(0, list.length)
.filter(i -> Arrays.stream(source)
.allMatch(l -> Arrays.binarySearch(l, list[i]) >= 0))
.collect(Collectors.toList()))
.collect(Collectors.toList());
如果需要,您可以添加toArray调用以转换为数组。