两个未排序的列表交叉点作为列表返回

时间:2018-10-11 13:33:18

标签: java list methods intersection linkedhashset

我的问题是,是否有可能获得2个未排序的列表,并根据其在第一个列表“ List1”中的顺序获取两个列表的交集。

public static List intersection(List A, List B) {

    List outcome = null;

    try {
        outcome = A.getClass().newInstance();
    } catch (Exception e) {};

    LinkedList<Integer> temp = new LinkedList<>();

    LinkedHashSet<Integer> ALinkedSet = new LinkedHashSet<>(A); 
    LinkedHashSet<Integer> BLinkedSet = new LinkedHashSet<>(B);

    // first filter elements into temp
    while (ALinkedSet.size() > 0) { 
        int v = ALinkedSet.removeFirst(); 
        if (BLinkedSet.contains(v)) { 
            temp.addLast(v);      
        }
    }

    // add filtered values back to L1
    while (temp.size() > 0) {     
        outcome.addLast(temp.removeFirst()); 
    }

    return outcome;
}

我正在寻找一种方法来完成这项工作,也许将其转为O(n)。

这是简单的方法。是否有更好的方法将大O变成线性?我很确定至少这是O(n * n)。

public static List Intersection(List A, List B) {

    List outcome = null;

    try {
        tulos = A.getClass().newInstance();
    } catch (Exception e) {};

    LinkedHashSet<Integer> AHashSet = new LinkedHashSet<>(A); 
    LinkedHashSet<Integer> BHashSet = new LinkedHashSet<>(B);

    for(Integer Aitem : AHashSet){
        for(Integer Bitem : BHashSet){
            if(Aitem==Bitem) {
                outcome.add(Aitem);
            }
        }
    }

    return outcome;
}

以下内容是否会线性出现?

public static List Intersection(List A, List B) {

 List outcome = null;

   try {
        tulos = A.getClass().newInstance();
    } catch (Exception e) {};

 LinkedHashSet<Integer> BHashSet = new LinkedHashSet<>(B);

    for(Object Aitem : A) {
        if(BHashSet.contains(Aitem) && !outcome.contains(Aitem)){
         outcome.add(Aitem);

           }
    }
    return outcome;

}

2 个答案:

答案 0 :(得分:1)

更新:由于我们只能使用LinkedHashMaps ...

...并且列表可以重复:

  1. 创建一个ListEntry类,该类具有数字和该数字在列表中重复的总次数。因此,如果2出现两次,我们将在LinkedHashMap(LHM)中创建一个new ListEntry(number: 2, count: 2);
  2. 使用第一个列表中的数字填充ListEntry对象的LHM;
  3. 现在,遍历第二个列表,逐一遍历其编号:
    1. 如果找不到第二个列表的号码,请继续下一个号码;
    2. 对于找到的每个数字,将其在LHM中的条目放在最前面,将其“可见”计数存储在哈希图(numberSeen)中,并更新另一个计数器(intersectionCount)来跟踪总相交到目前为止看到的数字;
  4. 在第二个列表上进行迭代后,您在LHM的前面有相交的数字;
  5. 现在使用numberSeenintersectionCount创建最终列表很简单。

运行时复杂度再次为O(m + n),空间复杂度为O(n)。


原始回复:

假设第一个列表的大小为 n ,第二个列表的大小为 m ,这是一种简单直接的解决方案,适用于O(m + n)时间和O(m + n)空间。

  1. 获取第二个列表,并将其所有元素放在将Integer映射到Integer的哈希映射中。这是为了跟踪列表中的重复项。如果列表中没有重复项,只需使用哈希集;
  2. 现在遍历第一个列表以及列表中的每个元素:
    1. 如果该元素存在于地图中并且具有正计数,则将该元素放入新列表中并减少其在地图中的计数;
    2. 如果该元素在地图中不存在或计数为0,请跳到列表中的下一个元素。

最后,您的新列表将包含两个列表的交集,按照它们在第一个列表中出现的顺序。


哈希表的总空间= m +新列表的n =。

总时间= m(用于将元素放入哈希图中),n(用于在第一列表上进行迭代)。

因此,O(m + n)时间和O(m + n)空间。

答案 1 :(得分:0)

怎么样:

LinkedHashSet<Integer> intersection = new LinkedHashSet<>(A).retainAll(new HashSet<>(B));

或者在List中获得输出:

List<Integer> intersection = new ArrayList<> (new LinkedHashSet<>(A).retainAll(new HashSet<>(B)));

实际上,这可能已经足够:

List<Integer> intersection = new ArrayList<> (A).retainAll(new HashSet<>(B));

由于retainAll的实现调用了传递的contains的{​​{1}},因此我们只需要将Collection转换为B就可以保持恒定的搜索时间

编辑:

要将建议的解决方案转换为线性时间解决方案,您应该利用HashSet查找时间:

HashSet