给定有限的数字序列,在每一轮中,将删除左邻居小于其自身的任何数字。此删除操作将继续,直到无法删除任何内容。删除的每个数字都将标记为已删除的圆形,如果永远不删除,则标记为0。
例如,考虑序列
0 9 8 7 9 8 7 5
在第一轮之后,它变成了,
0 8 7 8 7 5
并连续4轮后,
0 7 7 5
0 7 5
0 5
0
因此,数字的相应标签是
0 1 2 3 1 2 4 5
当N是所提供序列的长度时,如何通过使用堆栈或队列在O(N)时间内生成标签序列?或者我可以知道O(N)时间内最大轮次的移除?
答案 0 :(得分:1)
是的,可以使用单个堆栈完成,我将描述解决方案,并简要解释其后期工作的原因。
假设数组为A = [0, 9, 8, 7, 9, 8, 7, 5]
,Ans = [] be the array of corresponding answer
。我们还维护一个最初为空的堆栈S
。堆栈将存储对{A[i], Ans[i]}
,我们将尝试保留堆栈,使其在A[i]
上始终严格增加,如下所示:
{A[0], 0}
推送至S
循环遍历数组A
。对于迭代实例,让A[i]
为当前数字(Ans[i]
尚不知道):
2a上。初始化变量round_to_wait = 0
,不断弹出堆栈S
,直到顶部元素小于A[i]
,同时将rount_to_wait
设置为最大Ans[x]
2B。如果S
为空,则设置Ans[i] = 0
,否则设置Ans[i] = round_to_wait + 1
2c中。将{A[i], Ans[i]}
推送到S
让我们根据您的示例进行演示:
A = [0, 9, 8, 7, 9, 8, 7, 5], Ans = [0, -1, -1, -1, -1, -1, -1, -1], S = [{0,0}]
A[1] = 9 and S.top()
已小于9,未弹出任何元素。 Ans[1] = round_to_wait + 1 = 0 + 1 = 1
,将{9, 1}
推送到S
A = [0, 9, 8, 7, 9, 8, 7, 5], Ans = [0, 1, -1, -1, -1, -1, -1, -1], S = [{0,0}, {9,1}]
A[2] = 8
我们弹出元素,直到{0,0}
为止。 rount_to_wait = 1
因为它是整个弹出过程中的最大值。 Ans[2] = round_to_wait + 1 = 1 + 1 = 2
,将{8, 2}
推送到S
A = [0, 9, 8, 7, 9, 8, 7, 5], Ans = [0, 1, 2, -1, -1, -1, -1, -1], S = [{0,0}, {8,2}]
同样,S = [{0,0}, {7,3}]
同样,S = [{0,0}, {7,3}, {9,1}]
同样,S = [{0,0}, {7,3}, {8,2}]
同样,S = [{0,0}, {7,4}]
同样,S = [{0,0}, {5,5}]
就是这样,你在一个循环中得到答案。由于每个元素最多被推送和弹出一次,因此复杂性仍为O(N)
为什么它起作用是因为,让A[i]
成为第一个不与S
形成严格增加序列的元素,这是什么意思?
这意味着,在某些时候,S
S_top
中的顶部元素将“阻止”我们移除A[i]
。我们有机会(但不是充分条件)仅在A[i]
被删除时移除S_top
,这意味着它至少在Ans[S_top] + 1
时尽快删除,并且我们在所有这些元素中占据最大值。
特殊情况是,根本没有小于A[i]
的元素,这意味着S
最终将为空,在这种情况下Ans[i] = 0
(PS:我以为我几年前在一些在线评判中对这个问题有一些记忆,如果这是来源,你可以发布它以便我可以提交以验证解决方案吗?)