【问题标题】:Two unsorted lists Intersection returned as a list两个未排序的列表交集作为列表返回
【发布时间】:2019-03-16 14:46:03
【问题描述】:

我的问题是是否有可能获得 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;

}

【问题讨论】:

    标签: java list methods intersection linkedhashset


    【解决方案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. 获取第二个列表并将其所有元素放入一个哈希映射映射中,映射IntegerInteger。这是为了跟踪列表中的重复项。如果您的列表中没有重复项,只需使用哈希集即可;
    2. 现在遍历第一个列表和列表中的每个元素:
      1. 如果元素存在于地图中且计数为正,则将此元素放入新列表并减少其在地图中的计数;
      2. 如果该元素在地图中不存在或计数为 0,则跳至列表中的下一个元素。

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


    总空间 = m 用于 hashmap + n 用于新列表。

    总时间 = m 将元素放入 hashmap + n 用于迭代第一个列表。

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

    【讨论】:

    • 检查我的编辑。我只应该使用 LinkedHashSet。
    • @Masteprh33r:您的列表是否包含重复条目?
    • 是的,该列表包含一些重复项。
    • @Masteprh33r:我花了很多时间研究别人的代码并分析它对一般情况和边缘情况的正确性。因此,我提供了一个使用 LHM 并具有线性空间和时间复杂度的版本。
    • @Masteprh33r:此外,我的解决方案在复杂性上是线性的,而您的解决方案是二次的。
    【解决方案2】:

    怎么样:

    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的实现调用了传递的Collectioncontains,所以我们只需要将B转换为HashSet就可以得到恒定的搜索时间。

    编辑:

    要将建议的解决方案转换为线性时间解决方案,您应该利用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;
    }
    

    【讨论】:

    • 不使用诸如retainAll之类的预制方法,在引擎盖下有更多的了解。
    • 该解决方案会产生重复项。返回的 List 必须只包含一次相交元素。
    猜你喜欢
    • 2019-07-26
    • 2021-09-14
    • 1970-01-01
    • 2022-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多