【问题标题】:Merging a 2D array with sorted rows into a big 1D array将具有排序行的二维数组合并到一个大的一维数组中
【发布时间】:2016-12-28 17:49:06
【问题描述】:

给定一个二维数组,每行从左到右,从小到大排序,我想将整个数组从小到大排序为一维数组。

行数为N,列数为M。 我需要的复杂度是 MNlog(N)

我想做的是对 2d 数组进行某种合并排序,每次为函数发送 2 行,然后我就卡住了。

我为函数给出的签名是

void sort_rect(int a[N][M], int b[])

我保证 b 的一维数组有足够的空间容纳二维数组的所有元素。#C!!!

【问题讨论】:

  • 合并排序听起来确实像您需要的,将行合并到目标数组中。你能详细说明你的问题吗?你卡在哪一部分?合并排序一般?还有什么?
  • 我写了合并函数,复制函数,我被困在一个主要的事情上,首先是我如何每次发送 2 行然后将两行的 1d 数组存储在哪里?其次,我需要复杂性运行为 MN(log(N)) 而不是 MNlog(NM)
  • 输入(N = 3 ;M = 4):1 5 8 10 3 4 5 6 2 3 3 9 输出:1 2 3 3 3 4 5 5 6 8 9 10
  • 二维数组中的每一行(数组)是否已排序?

标签: c++ c arrays algorithm sorting


【解决方案1】:

由于a[M][N] 中的所有元素都驻留在顺序内存中,您可以将该内存视为平面内存。所以你像这样排序:

int *c = (int *)a;

并对c进行排序,假设数组的大小为M*N

或者你可以将它复制到b,通过像这样定义b

int b[sizeof(a) / sizeof(int)];
memcpy(b, a, sizeof(a));

现在对b进行排序。

【讨论】:

  • 元素总数为MN,OP 声明他想要一个复杂度为MN log(N)(不是MN log(MN))的排序算法。我不相信简单地对平面MN 数组使用通用排序算法会产生这样的MN log(N) 渐近性能。我猜这需要一些特定于问题的排序器(例如特定于问题的合并排序),利用长度为 M 的每个 N 子数组已经排序。
  • 我也有类似的想法,但我无法将其写入代码:(
【解决方案2】:

使用标准方法(合并排序的数组然后排序)会给你O(NMLog(NM))。如果你想要一种有效的方法,那么你应该使用最小堆数据结构。你可能想阅读堆数据结构。

  1. 创建一个大小为N*M的输出数组。这将保存输出排序后的数组。

  2. 创建一个大小为N的最小堆。插入每个排序数组的第一个元素。

  3. 从堆中删除顶部元素(最小值)并将其放入输出数组中。将此删除的元素替换为与此删除元素所在的同一数组中的下一个元素。重复此操作,直到所有元素都被计算在内为。

复杂度为O(NMLog(N))

【讨论】:

  • 注意 - 当到达每一行的末尾时,最小堆的行数和大小减少 1,直到只剩下一行的一部分,其中剩余的复制行以完成合并。
【解决方案3】:

考虑合并排序,但应用于 N 个数组而不是 2 个。对于每一行,您可以保留当前考虑元素的索引。现在我们需要一些东西来比较所有的 N 值(而不仅仅是 2)。您可以做的是使用具有如下元素结构的堆(priority_queue):

struct Element {
   int Value;
   int Row; //tells you which row in the 2d array the value comes from
}

算法如下:

  1. 您将列 0 中的所有值添加到优先级 排队
  2. 声明一个数组,它将保留当前考虑的每一行的索引。将其初始化为零。
  3. 在一个循环中(直到你用完元素)
    • 检查队列顶部的元素 (element = queue.top())
    • element.Value 添加到一维数组中
    • 当前考虑增加element.Row 的索引
    • 从优先队列顶部移除元素 (queue.pop())

得到的一维数组被排序,复杂度为 O(MNlog(N))。这是因为您考虑了 M*N 个元素,并且对于每个从 priority_queue 中添加/删除它的元素都需要 log(N) 时间,因为在任何给定时刻,堆保留的元素不超过 N 个。

我认为将 2d 数组视为 1d 并排序会导致 MNlog(MN) 复杂性更差。

【讨论】:

  • 上课怎么样?这也可能只是一个具有公共字段的类。
  • 这将是 N 路合并,而不是合并排序。
猜你喜欢
  • 2018-09-20
  • 1970-01-01
  • 2022-08-18
  • 1970-01-01
  • 2018-07-26
  • 1970-01-01
  • 1970-01-01
  • 2017-10-12
  • 2021-10-21
相关资源
最近更新 更多