【问题标题】:Getting N sorted items from an array of sorted arrays从排序数组的数组中获取 N 个排序项
【发布时间】:2013-06-26 01:30:25
【问题描述】:

我有一个多维日期数组,严格来说是ArrayList<ArrayList<Date>>。我需要生成一个新的一维ArrayList<Date>,它由前面提到的多维的所有数组中的项组成。

我的第一个想法是将所有的arraylists连接在一起并对其进行排序,但是由于我不知道每个级别的元素数量,并且只需要生成的数组中的一定数量的元素,那会有点太多的内存和处理器重。 我的意思是,如果我将所有 Date 元素加入到一个 ArrayList<Date> 中,我最终可能会得到一个包含数千个日期的数组列表......最终将其修剪到前 20 个。这就是我放弃该解决方案的原因。

那么,我可以使用哪种算法将 N(或 2)级的元素排序为 1?

编辑

ArrayList<Date> a1 = new ArrayList<Date>();
a1.add(new Date(15));
a1.add(new Date(16));
a1.add(new Date(23));

ArrayList<Date> a2 = new ArrayList<Date>();
a2.add(new Date(1));
a2.add(new Date(25));
a2.add(new Date(89));

ArrayList<Date> a3 = new ArrayList<Date>();
a3.add(new Date(64));
a3.add(new Date(72));
a3.add(new Date(73));

ArrayList<ArrayList<Date>> b = new ArrayList<ArrayList<Date>>();
b.add(a1);
b.add(a2);
b.add(a3);

我需要实现一个getLatestDates(ArryList&lt;ArrayList&lt;Date&gt;&gt;, Integer) 以便返回:

getLatestDates(b, 5) = {Date (89), Date(73), Date(72), Date(64), Date(25)};

在这个例子中只有 3 个ArrayList,但在实践中我不知道这个数字,所以我认为移动设备的最佳解决方案不是加入所有二级数组列表并排序新的大的,如果只使用一些项目的话。

【问题讨论】:

  • I need to generate...。只有尝试才会发生。
  • 您能说得更具体些吗?听起来您以正确的方式(至少在精神上)解决了它,并说这不是您想要的..
  • 在这两行之间,我读到您想要前 20 个日期,而不是对整个列表进行排序。这是一个不同的问题,并且具有比排序更快的解决方案。请清楚你想要什么。
  • @KarthikT 我最初对解决方案的想法非常耗费资源。如果我加入所有Date 元素,我最终可以处理大量日期,实际上我只需要使用其中的一部分。这就是为什么我认为我需要一个更优化的解决方案。
  • @Jago 混淆来自于你的问题正是这样问的。所以我希望你错过了一些细节,或者这个问题的措辞可能会更好。

标签: java android sorting multidimensional-array arraylist


【解决方案1】:

根据你对问题的描述,我能想到的一些解决方案是:

  1. 当然是您建议的,即附加所有数组,然后对它们进行排序并取其中的前 20 个。
  2. 分别对这些内部数组中的每一个进行排序,然后从合并排序算法执行类似合并的过程,以合并所有这些内部数组中的前 20 个项目,并在合并所需数量的项目时退出合并循环(例如 20 个项目)。
  3. 对这些内部数组中的每一个进行排序,同时将日期放入其中。这样您就不必在后面逐一遍历。然后像上面所说的那样进行合并。

如果您在多个内部数组中有多个项目,并且您想要其中的前 20 个,那么您将不得不遍历内部数组以某种方式排序。以上是我能想到的3个解决方案,欢迎大家补充。

编辑:

4。 我能想到的另一种方法是:通过扫描整个内部数组数组来构建优先级队列(最小堆)。这将是一个深度受限的树,即因为你想要 20 个元素,所以树的最大深度可以是 4(假设根为 0)。堆中允许的最大项目数为 20。这种方法将在 O(log N) 时间内为您提供解决方案。当然,您将花费 O(N) 时间来扫描整个列表中的每个项目,并且构建该堆可能会占用额外的空间。

【讨论】:

  • 第 2 点听起来很有趣。没有大量的日期,也没有锦标赛......似乎合理......
  • 是的,但是如果有许多包含许多元素的内部数组,这种方法可能会更糟。您将拥有的唯一优势是合并排序的最坏情况时间仍然是 O(N log N) 所以它仍然是一个胜利。所以要明智地选择。
  • 如果您正在考虑 2),想要以相当低的编程成本获得解决方案,并且对 O(n*logn) 复杂度感到满意,请尝试将所有日期收集在 TreeMap 中,它会自动对它们进行排序。然后你可以调用 myTreeMap.firstKey() n 次。如果要删除重复项,请改用 TreeSet。
【解决方案2】:

我建议tournament algorithm。这可能非常复杂,但会给你一个与 total 元素数量成线性关系的运行时间。

我会按照以下方式进行:

  1. 为每个列表创建一个锦标赛并存储锦标赛树(此树可能非常简单:每个元素,保存一个对手列表和结果)
  2. 在获胜者之间进行比赛并存储比赛树
  3. 第一个元素是锦标赛 2 的获胜者
  4. 第二个元素是锦标赛 1 或锦标赛 2 中获胜者的输家
  5. 第三个元素是 nr2 在锦标赛 1 或锦标赛 2 中的失败者
  6. 等等……

【讨论】:

  • 听起来不错的解决方案。我只是想知道它在移动设备中是否比合并单个数组列表中的所有元素并对其进行排序更消耗资源......?
  • @Jago 这是个好问题。存储将是O(n),但我不太确定常数。并且您需要一个 huge 数组,然后具有不良常量的线性算法优于具有良好常量的n log n 算法(例如默认的快速排序)。不过,当您遇到性能问题时,您可以考虑这种方法,因为您有很多日期。
  • 我认为这种方法占用了太多空间,考虑到它是在手机中完成的,几乎不可行。
猜你喜欢
  • 2022-06-27
  • 1970-01-01
  • 2021-02-05
  • 1970-01-01
  • 2013-06-17
  • 1970-01-01
  • 2018-06-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多