【问题标题】:Linear time algorithm for slicing stacked boxes对堆叠框进行切片的线性时间算法
【发布时间】:2013-12-19 02:55:48
【问题描述】:

我有一个时间限制相当有限的问题,我想看看我是否可以在正确的方向上获得帮助。

问题来了:

您会看到一堵墙,里面有不同高度的柱子。每一列的高度都表示为一个非零整数。

输入状态是使用长度为 N 的数组 H 定义的,包含每个高度 屏幕上的 N 列,例如:

在给定高度对快照进行切片会留下许多实心碎片 高于那个高度。例如。在第 2 级切片将切出 3 个实心块:

在第 1 层切片也会切出 3 个实心块:

类似地,在 0 级切片会返回一个(一个)实心片,而在 3 级切片不会切割任何片。

要求:给定一个长度为M的切片高度数组S,包含所有 应该执行“切片”的级别,返回一个长度为 M 的数组,其中包含每个切割的切割片数。

例如,给定输入 H = {2, 1, 3, 2, 3, 1, 1, 2}S = { 0, 1, 2, 3 },根据上面的示例,程序应该返回数量 {1, 3, 3, 0}

NM都在20,000左右的范围内,但每个数组的高度最高可达1,000,000。 p>

解决方案的时间和空间最坏情况复杂度不能超过 O(N + M + max(M) + max(N)).

最后一个约束让我感到困惑:它基本上意味着我不能有任何嵌套的for-loops,而且我似乎无法逃脱这一点。

显然,需要进行一些巧妙的预处理以在每个切片中产生 O(1) 的最终结果,但我一直无法想出。

我继续为每个切片级别创建一个切割编号数组,然后在遍历H 时更新所有这些编号,但结果是O(N*M),因为我需要更新所有较低的高度水平。

是否有适合此任务的数据结构?

【问题讨论】:

  • 要挑剔这个问题,您不能使用简单的高度数组来表示所有可能的俄罗斯方块状态。如果你这样做了,那么你永远不会在一个实心块下面有一个空白空间。这个问题更像是对与邻居共享外墙的建筑物进行切片。
  • @Kevin:正确,我可能会更改标题以反映这一点。
  • 你知道,当你说数据结构的时候,马上想到的是binary indexed treeMore info
  • 只是为了清楚并切断一些陈述 - 问题归结为给你一个整数数组,你应该能够回答how many contiguous regions of high no greater than X exist类型的快速查询
  • @Ivaylo:是的,就是这样。我假设在O(N + C) 预处理之后,我应该能够在O(1) 中为每个X 获取区域计数。

标签: algorithm


【解决方案1】:

对于处于某个高度的每一块,必须有两条边与该高度相交,并且根据“块”的定义,这些边集的成员都必须是不同的。所以片数是集合中边数的一半。

此外,与特定高度相交的边数是在该高度以下或该高度处开始的边数减去在该高度以下或在该高度处结束的边数。

因此,我们可以这样计算件数:

  • 创建一个数组Accumulator,大小为max(S),用零填充。
  • 遍历H,并为遇到的每个垂直边缘在索引i 处添加一个+1,在Accumulator 对应于边缘下端的高度,并在索引处添加一个-1 j 对应于边缘的上端。我们将“地平面”计算为零。确保包括前缘和后缘!
  • 迭代 Accumulator 并在每个单元格中插入所有单元格的总和,直到并包括它(O(max(S)) 时间,如果您保持运行总和)
  • Accumulator 中的每个值除以2,得到每个高度处的碎片数。
  • 读出S中高度对应的件数。

例子:

边缘的端点,从左到右,是

0,2
1,2
1,3
2,3
2,3
1,3
1,3
0,3

所以我们的Accumulator 数组看起来像这样:

{2, 4, 0, -6}

在累积步骤之后,如下所示:

{2, 6, 6, 0}

这意味着零件数是

{1, 3, 3, 0} 

作为警告,我只是当场提出这个想法,所以虽然感觉正确,但我无法证明它是否真的如此。令人鼓舞的是,它也适用于我尝试过的其他一些令牌示例。

【讨论】:

  • 谢谢,太好了。这非常简单。不敢相信我花了这么多时间试图将其融入复杂的算法中。 :)
【解决方案2】:
Step 1: Maintain 3 column list (height, index_start, index_end)
Step 2: Sort the list according to height as primary key (decreasing), index_start as secondary key
Step 3: Let h be the highest height
Step 4: Merge all columns at height at least h and contiguous block
Step 5: Resulting number of blocks is blocks at height h
Step 6: h=h-1
Step 7: Go to step 4

这是粗略的算法。实际上复杂度是 O(nlogn)

【讨论】:

  • +1 谢谢,这实际上看起来很有希望,同时也非常简单明了。不过有几个问题,只是为了检查我是否正确:(index_start, index_end) 对代表什么?单个 H 上方的每个方形框的开始和结束? IE。对于H=2,我会有三个这样的行吗?另外,第4步的复杂性是多少?另外,我认为O(NlogN) 是由于排序所致?在这种情况下,最好将它们全部放在一个哈希集中 (H -> (start,end)),对吧?
  • 唯一让我担心的是第 1 步。创建列列表的位置看起来像 O(N*M)?
  • @LousyCoder 这一步是 O(nlogn),因为它只涉及排序。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-29
  • 2020-03-25
  • 2015-10-30
  • 2017-05-26
  • 2020-08-04
  • 1970-01-01
相关资源
最近更新 更多