【问题标题】:How to efficiently sort one million elements?如何高效地对一百万个元素进行排序?
【发布时间】:2015-07-08 13:52:59
【问题描述】:

我需要将大约 60.000 与 935.000 个元素的列表进行比较,如果它们匹配,我需要执行计算。

我已经实现了所需的一切,但该过程大约需要 40 分钟。我在两个列表中都有一个唯一的 7 位数字。 935.000 和 60.000 文件未排序。在我尝试查找元素之前对大列表进行排序(哪种排序?)效率更高吗?请记住,我每个月只需进行一次此计算,因此我不需要每天都重复该过程。

基本上哪个更快:

  • 未排序的线性搜索
  • 先排序列表,然后用另一种算法搜索

【问题讨论】:

    标签: java performance sorting arraylist


    【解决方案1】:

    试试看。

    Collections.sort() 可以为您完成繁重的工作,Collections.binarySearch() 可以让您在排序列表中找到元素。

    【讨论】:

      【解决方案2】:

      当您搜索未排序的列表时,您必须平均浏览一半的元素才能找到您要查找的元素。当你在 935,000 个元素的列表上执行 60,000 次时,结果大约是

      935,000 * 1/2 * 60,000 = 28,050,000,000 次操作

      如果您首先对列表进行排序(使用合并排序),则大约需要 n * log(n) 次操作。然后,您可以使用二进制搜索在 log(n) 查找中为您的短列表中的 60,000 个元素中的每一个查找元素。就是这样

      935,000 * log(935,000) + log(935,000) * 60,000 = 19,735,434 次操作

      如果先对列表进行排序,然后使用利用排序列表的搜索算法,应该会快很多。

      【讨论】:

      • 但是要对列表进行排序,我必须遍历每个元素,不管我错了吗? *** 我现在明白了,谢谢,太好了!
      【解决方案3】:

      最好对两个列表进行排序,然后同时遍历这两个列表。

      使用 collections.sort() 对列表进行排序。

      您从每个排序列表的索引开始,然后基本上直接遍历它。您从短列表中的第一个元素开始,并将其与长列表中的第一个元素进行比较。如果您到达长列表中的某个元素的 7 位数字高于短列表中的当前编号,请增加短列表的索引。这样就不需要检查元素两次了。

      但实际上,既然你想找到两个列表的交集,你最好只使用longList.retainAll(shortList) 来获取两个列表的交集。然后你可以在 O(1) 左右的两个列表上执行任何你想要的操作,因为实际上不需要找到任何东西。

      【讨论】:

      • 遍历排序集合以查找元素是低效的。二进制搜索是要走的路。
      • 不一定。在这种情况下(搜索长列表中的大量元素)实际上可能非常快,因为它不需要搜索整个列表。通过保留索引,您将大大减少负载。
      • 好的,我知道你在那里做了什么。首先,我以为您的意思是 for(;;){ for(;;){ ... }} 具有“静态”边界。
      • 感谢您的 cmets,因为他们让我思考。 OP 实际上想要找到两个列表中的所有元素,所以他在两个列表的交集之后。有一个函数可以做到这一点,list.retainAll()
      • 好吧,我隐瞒了一些信息,我有 3 个列表,一个带有 key1,一个带有 key1 和 key2(935000 个元素),第三个带有 key2,我只需要使用 key1 更改列表key2 列表
      【解决方案4】:

      您可以根据需要对两个列表进行排序并逐个元素地比较它们,增加第一个或第二个索引(ij,在下面的示例中):

      List<Comparable> first = ....
      List<Comparable> second = ...
      Collections.sort(first);
      Collections.sort(second);
      
      int i = 0;
      int j = 0;
      while (i < first.size() && j < second.size()) {
          if (first.get(i).compareTo(second.get(j)) == 0) {
              // Action for equals
          }
          if (first.get(i).compareTo(second.get(j)) > 0) {
              j++;
          } else {
              i++;
          }
      }
      

      这段代码的复杂度是 O(n log(n)),其中 n 是最大的列表大小。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-05-05
        • 1970-01-01
        • 1970-01-01
        • 2020-06-02
        • 1970-01-01
        • 2020-05-24
        • 1970-01-01
        相关资源
        最近更新 更多