【问题标题】:Which is more efficient, Sorting and then Binary Search over a Collection or Linear Search in java哪个更有效,排序然后二进制搜索在Java中的集合或线性搜索
【发布时间】:2014-07-15 03:19:40
【问题描述】:

假设我有一个对象集合:

List<String> myList = populateMyArrayList();
//Here I am having an ArrayList with 1000 elements

哪种方法更好:

1 : 合并排序然后二分查找

Collections.sort(myList);
int keyIndex = Collections.binarySearch(myList, key);

2:顺序搜索

for(String s : myList){
   if(s.equals(key)){
      return s;
   }
}

根据要搜索的集合的大小,搜索方法是否应该有所不同?如果是,那么如何决定。

EDIT1:假设我必须搜索列表几次,并且列表中不会添加新元素。

EDIT2:我本来可以选择HashSet,但实际上我有一个List&lt;CustomObject&gt;,我可以根据CustomObject 的不同属性多次搜索List。所以我的 CustomObject 中不能有一个被覆盖的 equals 方法

【问题讨论】:

  • 第一种方法将在 O(nlogn) 时间内运行(由于排序),而线性搜索的运行时间为 O(n)。
  • 当然是线性搜索。 O(n) 与 O(nlogn + logn) = O(nlogn)
  • 别忘了myList.contains(key)
  • 我觉得这个问题更适合Programmers SE
  • 您要在列表中搜索多少次?您要插入多少次项目?除非你对这些问题有一个明确的答案,否则我们给你的任何答案都是毫无意义的。

标签: java collections binary-search mergesort linear-search


【解决方案1】:

视情况而定。

  • 如果您只搜索一个字符串,线性搜索会更好,因为它位于O(n)
  • 如果您要搜索多个字符串,首先排序然后二进制搜索可能会更好。它将是O(logn + n*logn),即O(n*logn)。因此,如果您正在检查 ca。 n 字符串,这个更好。
  • 如果您只想知道您的集合是否包含一个元素(忽略顺序),您应该考虑使用具有O(1)HashSet
  • 如果您需要订购和快速包含方法,请使用LinkedHashSet

附:过早优化是万恶之源。

【讨论】:

  • 这还为时过早吗?
  • 他没有检查一个简单的解决方案是否满足他的需求。
  • 值得一提的是,“大 O”表示法将算法的行为表示为 n 变化,但这并不意味着对于给定的 n 值,一种算法比另一种算法“更快” .对于给定的nlog(n) 算法可能比O(n^2) 算法慢(如果n 足够大,最终具有更好功能的算法将获胜,但这样的n 值可能很大足以毫无意义)。并不是说这个 cmets 只属于你的答案,而是我不得不把它贴在某个地方。
  • @SJuan76 Big O 假设n 趋于无穷大,所以它没有说小n
  • 这是我的观点...对于有限的值(在这种情况下为1000),确定哪种算法“更快”并不容易。
【解决方案2】:

如果您只进行一次搜索:

  • 排序+二分查找的复杂度为O(n * log n)
  • 线性搜索的复杂度为O(n)

如果您搜索不止一次,比如说k 次:

  • 排序+二分查找的复杂度为O((n + k) * log n)
  • 线性搜索的复杂度为O(k * n)

因此,如果您只进行一次搜索,您应该使用线性搜索。如果您进行多次搜索,很可能您应该首先进行排序。

此外,也许在这种情况下,您可以考虑使用哈希表,它的元素搜索的摊销复杂度为 O(1)

【讨论】:

  • 排序+二分查找的复杂度为 O(nLogn + log n) 而不是 O(n * log n)
  • @TheLostMind 在复杂性理论中,O(n * log n + log n) 被认为等于 O(n * log n),因为只有排名最高的项才被认为是重要的。请同时检查此问题的其他答案,并重新考虑您的反对票。
  • 在 k 次运行的情况下,排序 + 二进制搜索的复杂性只有在 k >> n 时才会为 O(k * log n),如果 k = 1,它肯定会保持 O(n * log n)。我认为正确的复杂度是 O( (k + n)*log n) 或者至少需要一些解释。
  • @bosonix - 我的错。我以为您已将合并排序的复杂性输入为“n”。请下次更清楚。
  • @AndreiBozantan 为什么是 O(n * log n) ?快速排序(假设这是语言中最常见的排序)复杂性可以忽略二进制搜索复杂性吗?
【解决方案3】:

如果您只搜索列表一次(或很少)线性搜索更便宜。如果您更频繁地搜索列表,则可以偿还排序成本。排序成本 O(n log n) 平均时间复杂度和搜索然后 O(log n)。如果您搜索几乎“每个元素”,这也会花费 O(n) 平均时间复杂度,并且您在排序方面是“偶数”。

【讨论】:

    【解决方案4】:

    二进制搜索是 O(log(m)) 并且比 O(n) 的线性搜索要快。 但是必须先对数据进行排序:O(n log(n)),这需要更长的时间。

    因此,如果数据填充一次,然后经常寻找,请进行排序和二进制搜索。 更好的是:拿一套。 HashSet 会更好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-05
      • 2021-11-24
      • 2012-05-18
      • 1970-01-01
      • 1970-01-01
      • 2017-11-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多