[LC]验证栈序列

97 阅读2分钟

这是我参与2022首次更文挑战的第28天,活动详情查看:2022首次更文挑战

题目

946. 验证栈序列 - 力扣(LeetCode) (leetcode-cn.com)

解析

观察题目给出的条件:

  • 数字不会重复。

这代表了每个元素在栈中都是不会重复的,也就意味着弹出的时机也是确定的,不会有在某时刻既可以选择弹出也可以继续压栈的情况。

这也就意味着,对于某个出栈顺序,入栈顺序就是固定的

因此,题目描述的既然是栈,必然可以使用栈来进行。

而出栈的时机,有2个:

  • 要么是在某次入栈的时候,发现栈顶的元素和当前需要出栈的元素相等,那么就执行出栈,直到栈为空或不相等。
  • 在入栈结束后,栈中还有元素的时候,那么执行和上述相同的操作。

最后,判断栈是否为空即可。

代码:

public boolean validateStackSequences(int[] pushed, int[] popped) {
    int popIdx = 0;
    Deque<Integer> stack = new ArrayDeque<>();
    for (int i = 0; i < pushed.length; i++) {
        stack.push(pushed[i]);
        while(!stack.isEmpty() && popped[popIdx] == stack.peek()){
            stack.pop();
            popIdx++;
        }
    }
    while(!stack.isEmpty() && popped[popIdx]==stack.peek()){
        stack.pop();
        popIdx++;
    }
    return stack.isEmpty();
}

结果:

执行用时:1 ms, 在所有 Java 提交中击败了95.16%的用户

内存消耗:40.8 MB, 在所有 Java 提交中击败了31.50%的用户

使用指针模拟

注意到给定的值范围在[0,1000],那么可以不使用栈来解决这个问题。

具体的思路就是,对于”出栈“的,我们用一个-1来表示,这样子就可以省去对于出栈部分的记录。

思路和上面的类似,只不过不再使用栈进行模拟,仅用数组来做。

代码如下:

public boolean validateStackSequences2(int[] pushed, int[] popped){
    int popIdx = 0;
    for (int i = 0; i < pushed.length; i++) {
        if(popped[popIdx] != pushed[i]) continue;
        int tmp = i;
        while(popIdx<pushed.length && tmp>=0){
            while(tmp>=0&&pushed[tmp]==-1) tmp--;
            if(tmp<0 || popped[popIdx]!=pushed[tmp]) break;
            pushed[tmp] = -1;
            popIdx++;
            tmp--;
        }
    }
    return popIdx == popped.length;
}

结果:

执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户

内存消耗:41.3 MB, 在所有 Java 提交中击败了5.02%的用户