这是我参与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%的用户