【问题标题】:What is the best optimized way to find if a list contains every element of another list?查找列表是否包含另一个列表的每个元素的最佳优化方法是什么?
【发布时间】:2016-09-19 13:58:47
【问题描述】:

我有两个列表:

List<String> firstList = new LinkedList<String>();
List<String> secondList = new LinkedList<String>();

我想知道一个列表的每个元素是否都包含在另一个列表中。 一个可能的解决方案是:

public boolean function(List<String> first, List<String> second)
{
first = firstList;
second = secondList
for (String item : firstList)
    {
            for (String elem : secondList)
            {
                if(elem.compareTo(item)!=0)
                return false;
            }
    }
 return true;
 }

正如我们所见,时间是二次方的。有没有更好的办法?

【问题讨论】:

  • 为什么不直接使用containsAll
  • firstList 和contains list 方法可以使用一个foreach。
  • @resueman 因为constainsAll 使用线性搜索。
  • 您的方法通常会在应该返回true 时返回false,因为您返回false 太早了。

标签: java list time-complexity


【解决方案1】:

你有一个 O(n*m) 的实现,需要 O(1) 空间;您可以通过将第一个列表的元素添加到HashSet&lt;String&gt;,然后验证第二个列表的所有元素都存在,来实现具有 O(m) 空间要求的 O(n+m):

Set<String> firstSet = new HashSet<String>(firstList);
for (String elem : secondList) {
    if(!firstSet.contains(item)) {
        return false;
    }
}
return true;

甚至更好

return new HashSet<>(firstList).containsAll(secondList);

(谢谢,bradimus!)

注意:您的方法使用次优比较机制:您可以调用equals,而不是调用compareTo,因为您不需要检查单词是否按字母顺序排列在前面或后面.

另一个问题是,您的方法通常会在应该返回 true 时返回 false,因为您返回 false 太早了。

【讨论】:

  • 对 OP 解决方案的良好观察。我相信您的可以缩短为 return new HashSet&lt;&gt;(firstList).containsAll(secondList); 而不会失去清晰度。
【解决方案2】:
public boolean function(List<String> first, List<String> second) {
    return (second.size() == first.size() && first.containsAll(second))
}

【讨论】:

  • 这会检查两个列表是否包含完全相同的元素,而不是较大的列表包含较小列表的所有元素。
  • @SirCelsius 是对的......但这可能只是containsAll() 方法使用的变化......对于更大的列表,它可能是这样的return first.size() &gt;= second.size() ? first.containsAll(second) : second.contains(first)
【解决方案3】:

根据一个或两个列表是否定期更改,您可能会发现将HashSet&lt;String&gt; 用于很少更改的列表更有效。

更多详情请见Set operations: union, intersection, difference, symmetric difference, is subset, is superset

【讨论】:

    【解决方案4】:

    试试这个:

    !Collections.disjoint(list1, list2);

    或者你可以使用containsAll

    希望对你有帮助!

    【讨论】:

      【解决方案5】:
       return first.containsAll(second);
      

      【讨论】:

        【解决方案6】:

        我相信有an existing answer 可以解决您的问题。

        这个想法基本上是使用两个Set并计算它们的交集的大小。

        我相信,如果您负担得起使用Set 而不是List,那么您可以在contains 上节省时间。无论发生什么,您都将拥有o(n) 的复杂性。


        编辑

        如果您关心匹配输入列表中的重复项,上述解决方案可能效率不高。你可能要小心。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-08-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-04-14
          • 1970-01-01
          • 2021-02-18
          • 2012-11-09
          相关资源
          最近更新 更多