如何测试弹出订单是否合法?

时间:2013-07-23 23:54:34

标签: algorithm

鉴于两个唯一的数字序列:push order of stackpop order of stackpush order中的数字按升序排序,现在要求pop order合法与否?

例如,push order是1 2 3 4 5,所以4 5 3 2 1是合法的弹出订单,因为我们可以像这样推送和弹出:

push 1, push 2, push 3, push 4, pop, push 5, pop, pop, pop, pop

所以弹出订单:4 5 3 2 1是合法的,4 3 5 1 2不是合法的弹出订单。

4 个答案:

答案 0 :(得分:4)

由于您的推送顺序是按升序排列的,那么当您在弹出队列中看到一个数字N时,则 所有数字1)低于N且2)尚未弹出,必须按降序弹出。

例如,4 3 5 1 2不是有效订单,因为当我们看到'4'弹出时,所有数字都是 小于'4'但尚未弹出之前必须按降序弹出。但是,首先弹出'1'然后再弹出'2'会违反此属性。

答案 1 :(得分:3)

一种选择是实际构建堆栈:

对于弹出顺序中的每个数字X

  • 如果此数字与堆栈顶部不同(或堆栈为空),请按推送顺序中的数字,直到您按下X。如果您推送了所有数字而没有找到X,则无法获得弹出订单。
  • Pop X

请注意,这实际上并不要求推送顺序是升序。

如果X小于堆栈的顶部,您可以利用排序来稍微优化上述(先前失败)失败。

由于你最多只推动一次元素,上面是线性时间(你不能做得更好)和线性空间。

示例:

Push: 1 2 3 4 5  
Pop: 4 5 3 2 1

Processing: 4
    Stack empty -> push until 4 is on the top of the stack.
    Stack: 1 2 3 4
    Pop 4
    Stack: 1 2 3

Processing: 5
    3 != 5 -> push until 5 is on the top of the stack.
    Stack: 1 2 3 5
    Pop 5
    Stack: 1 2 3

Processing: 3
    Pop 3
    Stack: 1 2

Processing: 2
    Pop 2
    Stack: 1

Processing: 1
    Pop 1
    Stack: 

Done.

答案 2 :(得分:1)

<强>解决方案:

i: from 1 to n
j: from 1 to n, used to traverse the sequence seq[1...n]
stack: empty at the beginning
while i <= n || j <= n
    IF stack is empty,
        push i into stack, i plus 1;
    ELSE IF the top of stack is equal to seq[j]
        pop from stack, j plus 1;
    ELSE IF the top of stack is larger than seq[j]
        illegal sequence! Stop here!
    ELSE 
        push i into stack, i plus 1;
legal sequence if the stack is empty!

示例1:{1,2,4,3},合法序列

In the beginning, i = 1, j = 1, and stack is empty.

1. stack is empty: 
   stack = {1}, i = 2, j = 1.

2. top of stack 1 is equal to seq[j] = 1: 
   stack = {}, i = 2, j = 2.

3. stack is empty: 
   stack = {2}, i = 3, j = 2.

4. top of stack 2 is equal to seq[j] = 2: 
   stack = {}, i = 3, j = 3.

5. stack is empty: 
   stack = {3}, i = 4, j = 3.

6. top of stack 3 is smaller than seq[j] = 4: 
   stack = {3, 4}, i = 5, j = 3.

7. top of stack 4 is equal to seq[j] = 4: 
   stack = {3}, i = 5, j = 4.

8. top of stack 3 is equal to seq[j] = 3:
   stack = {}, i = 5, j = 5.

示例2:{1,4,2,3},非法序列

In the beginning, i = 1, j = 1, and stack is empty.

1. stack is empty: 
   stack = {1}, i = 2, j = 1.

2. top of stack 1 is equal to seq[j] = 1: 
   stack = {}, i = 2, j = 2.

3. stack is empty: 
   stack = {2}, i = 3, j = 2.

4. top of stack 2 is smaller than seq[j] = 4: 
   stack = {2, 3}, i = 4, j = 2.

5. top of stack 3 is smaller than seq[j] = 4: 
   stack = {2, 3, 4}, i = 5, j = 2.

6. top of stack 4 is equal to seq[j] = 4: 
   stack = {2, 3}, i = 5, j = 3.

7. top of stack 3 is larger than seq[j] = 2: 
   illegal sequence, stop here.

我正在尽力解释我的想法,希望我已经说清楚了。

答案 3 :(得分:1)

假设:推送顺序和弹出订单包含完全相同的数字。如果这不是一个有效的假设,可以在线性时间内使用哈希集(或带有计数的哈希映射,如果可能存在重复)进行验证,尽管这会损害O(1)空间复杂度。

想法:弹出顺序中的每个元素必须小于之前的元素,或者大于目前为止的最大值,否则弹出顺序无效。

只需跟踪最大值,即可在O(n)时间和O(1)空间中进行检查。

为什么会这样:

推送顺序按升序排列,因此,无论何时弹出元素:

  1. 堆栈也将始终按升序排列
  2. 推送顺序中的下一个项目将始终大于堆栈中看到的最大元素。
  3. 所以有两种选择:

    • 连续两次弹出操作 - 在这种情况下,第二个元素将更小
    • 两次弹出操作,其间有一个或多个推动操作 - 在这种情况下,第二个元素将大于最大值(从2开始)。

    <强>示例:

    4 5 3 2 1自5&gt;开始有效max(4),3&lt; 5,2&lt; 3和1&lt; 2。

    4 3 5 1 2无效,因为2&gt; 1但是2&lt;最大(5)。

    1 2 3 5 4有效,因为2&gt; max(1),3&gt; max(2),5&gt; max(3)和4&lt; 5。