简体   繁体   English

在java中查找arraylists中常见元素的索引

[英]Find indices of common elements in arraylists in java

I have several ArrayLists with no repeated elements. 我有几个没有重复元素的ArrayLists。 I want to find their intersection and return indices of common elements in each arraylist. 我想在每个arraylist中找到它们的交集并返回常用元素的索引。
For example, if I have input as {0,1,2},{3,0,4},{5,6,0} , then I want to return {0},{1},{2} ie indices of common element 0 here. 例如,如果我输入为{0,1,2},{3,0,4},{5,6,0} ,那么我想返回{0},{1},{2}即索引这里的共同元素0。
One way I can think of is to use succesive retainAll() on all ArrayLists to get intersection, and then finding indices of elements of intersection using indexOf() for each input ArrayList. 我能想到的一种方法是在所有ArrayLists上使用连续的retainAll()来获取交集,然后使用indexOf()为每个输入ArrayList查找交集元素的索引。
Is there a better way to do that ? 有没有更好的方法呢?

Sorting the list first would require at least O(nlogn) time. 首先对列表进行排序至少需要O(nlogn)时间。 If you are looking for a more efficient algorithm you could get O(n) using hashmaps. 如果您正在寻找更高效的算法,您可以使用哈希映射获得O(n)

For example with 例如用

A=[0,1,2],B=[3,0,4],C=[5,6,0]

You can loop through each list and append elements with a hash on the element. 您可以循环遍历每个列表,并在元素上添加带有哈希的元素。 The final hash will look like 最终的哈希看起来像

H = {0:[0,1,2], 1:[1], 2:[2], 3:[0], 4:[2], 5:[0], 6:[1]}

Here, the key is the element, and the value is the index in it's corresponding list. 这里,键是元素,值是其对应列表中的索引。 Now, just loop through the hashmap to find any lists that have a size of 3, in this case, to get the indices. 现在,只需循环遍历hashmap,找到大小为3的任何列表,在这种情况下,获取索引。


The code would look something like this (untested): 代码看起来像这样(未经测试):

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());
    }
}

EDIT: Just noticed you suggested using retainAll() in your question. 编辑:刚刚注意到你建议在你的问题中使用retainAll()。 That would also be O(n). 那也是O(n)。

Here is a very inefficient but fairly readable solution using streams that returns you a list of lists. 这是一个非常低效但相当可读的解决方案,使用流返回列表列表。

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());

You can add toArray calls to convert to arrays if required. 如果需要,您可以添加toArray调用以转换为数组。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM