用于生成表示删除数字序列的序列的算法

时间:2017-03-12 14:34:23

标签: algorithm stack queue

给定有限的数字序列,在每一轮中,将删除左邻居小于其自身的任何数字。此删除操作将继续,直到无法删除任何内容。删除的每个数字都将标记为已删除的圆形,如果永远不删除,则标记为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)时间内最大轮次的移除?

1 个答案:

答案 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]上始终严格增加,如下所示:

  1. {A[0], 0}推送至S
  2. 循环遍历数组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

  3. 让我们根据您的示例进行演示:

    1. A = [0, 9, 8, 7, 9, 8, 7, 5], Ans = [0, -1, -1, -1, -1, -1, -1, -1], S = [{0,0}]
    2. 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}]

    3. 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}]

    4. 同样,S = [{0,0}, {7,3}]

    5. 同样,S = [{0,0}, {7,3}, {9,1}]

    6. 同样,S = [{0,0}, {7,3}, {8,2}]

    7. 同样,S = [{0,0}, {7,4}]

    8. 同样,S = [{0,0}, {5,5}]

    9. 就是这样,你在一个循环中得到答案。由于每个元素最多被推送和弹出一次,因此复杂性仍为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:我以为我几年前在一些在线评判中对这个问题有一些记忆,如果这是来源,你可以发布它以便我可以提交以验证解决方案吗?)