Given two sequences pushed
and popped
with distinct values, return true
if and only if this could have been the result of a sequence of push and pop operations on an initially empty stack.
Origin:
/**
* 循环遍历入栈序列模拟,用栈s模拟出入栈操作,每次循环默认入栈一个元素,用pop_index记录在入栈过程中已完成的出栈位置
* 情况1: 下一个入栈正好等于下一个出栈,pop_index++,1出1入
* 情况2: 栈顶等于下一个出栈,pop_index++,push_index--让其经过本次循环不增,1出0入
* 情况3: 下一个入栈、栈顶都不等于下一个出栈,0出1入
* 入栈序列操作完后,只需比较栈中剩余元素出栈顺序与从pop_index开始的出栈数组顺序是否一致
*/
class Solution {
public boolean validateStackSequences(int[] pushed, int[] popped) {
if (pushed == null && popped == null)
return true;
if (pushed == null || popped == null || pushed.length != popped.length)
return false;
Stack<Integer> s = new Stack<Integer>();
int pop_index = 0;
for (int push_index = 0; push_index < pushed.length; push_index++) {
if (popped[pop_index] == pushed[push_index]) { // 情况1
pop_index++;
continue;
}
if (!s.isEmpty() && s.peek() == popped[pop_index]) { // 情况2
s.pop();
push_index--;
pop_index++;
continue;
}
s.push(pushed[push_index]); // 情况3
}
while (!s.isEmpty())
if (s.pop() != popped[pop_index++])
return false;
return true;
}
}
Modified:
/**
* 1. 下一个入栈等于下一个出栈的情况可不单独考虑,只分为栈顶等于、不等于下一个出栈这两种情况,只要不等于栈顶都push进s
* 2. 循环可以优化,只需要一个while循环,continue也可以写成else if缩短代码
*/
class Solution {
public boolean validateStackSequences(int[] pushed, int[] popped) {
if (pushed == null && popped == null)
return true;
if (pushed == null || popped == null || pushed.length != popped.length)
return false;
Stack<Integer> s = new Stack<Integer>();
int pop_index = 0, push_index = 0;
while (pop_index < popped.length) {
if (!s.isEmpty() && s.peek() == popped[pop_index]) {
s.pop();
pop_index++;
}
else if (push_index < pushed.length)
s.push(pushed[push_index++]);
else
return false;
}
return true;
}
}
总结:
- 经典题,判断是否为可能的出栈顺序,记得用一个栈辅助
- 适合用遍历popped数组而非遍历pushed数组做循环:因为push完之后大概率还要出栈,得分两个循环;而pop完题目包含的所有过程就结束了,只需要一个循环
- 适合用while循环:因为一次循环中没有一定要增的量(如第二种解法中循环一次可能增push_index或pop_index或两者都不增)
- 注意continue和else if的选择。