我遇到一个时间限制相当有限的问题,并希望看看我是否可以在正确的方向上轻推。
问题在于:
你会看到一面墙上有不同高度的柱子。每列高度表示为非零整数。
使用长度为
H
的数组N
定义输入状态,其中包含每个高度 屏幕上的N
列,例如:
在给定高度切片快照会留下许多实心碎片 高于那个高度。例如。在2级切片会削减3个实体:
在第1级切片也会削减3个实体:
同样,在0级切片会返回单个(一个)实体块,而在3级切片则不会切割任何碎片。
要求:给定长度
S
的切片高度M
数组,包含所有切片高度 应执行“切片”的级别,返回长度M
的数组,其中包含每个切割的切割件数。例如,根据输入
H = {2, 1, 3, 2, 3, 1, 1, 2}
和S = { 0, 1, 2, 3 }
,根据上面的示例,程序应返回数量{1, 3, 3, 0}
。
N
和M
都在20,000
左右,但每个数组的高度最高可达到1,000,000
。解决方案的时间和空间最坏情况复杂性都不能超过
O(N + M + max(M) + max(N))
。
最后一个约束让我感到困惑:它基本上意味着我不能拥有任何嵌套的for
- 循环,而我似乎无法摆脱这种情况。
显然,有一些聪明的预处理需要在每片O(1)
中产生最终结果,但我无法想出它。
我继续为每个切片级别创建一个切割数字数组,然后在迭代H
时更新所有切割数字,但事实证明这是O(N*M)
,因为我需要更新所有较低的高度。
是否有适合此任务的数据结构?
答案 0 :(得分:5)
对于高度上的每个部件,必须有两个与该高度相交的边缘,并且通过“部件”的定义,这组边缘的成员必须全部是不同的。因此,件数是集合中边数的一半。
此外,与特定高度相交的边数是在下方或该高度处开始的边数,减去在其下方或下方完成的边数。
因此,我们可以通过这种方式计算出件数:
Accumulator
的数组max(S)
,其中填充了零。H
进行迭代,对于您遇到的每个垂直边缘,在+1
的索引i
处添加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}
作为警告,我刚刚在现场提出这个问题,所以虽然感觉正确,但我没有证据确实是这样。令人鼓舞的是,它也尝试了我尝试过的其他几个例子。
答案 1 :(得分:1)
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)