给定 pushed
和 popped
两个序列,每个序列中的 值都不重复,只有当它们可能是在最初空栈上进行的推入 push 和弹出 pop 操作序列的结果时,返回 true
;否则,返回 false
。
示例 1:
输入:pushed = [1,2,3,4,5], popped = [4,5,3,2,1] 输出:true 解释:我们可以按以下顺序执行: push(1), push(2), push(3), push(4), pop() -> 4, push(5), pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1
示例 2:
输入:pushed = [1,2,3,4,5], popped = [4,3,5,1,2] 输出:false 解释:1 不能在 2 之前弹出。
提示:
1 <= pushed.length <= 1000
0 <= pushed[i] <= 1000
pushed
的所有元素 互不相同popped.length == pushed.length
popped
是pushed
的一个排列
解法1:栈模拟
这道题需要利用给定的两个数组 pushed 和 popped 的如下性质:
- 数组 pushed 中的元素互不相同;
- 数组 popped 和数组 pushed 的长度相同;
- 数组 popped 是数组 pushed 的一个排列。
根据上述性质,可以得到如下结论:
- 栈内不可能出现重复元素;
- 如果 pushed 和 popped 是有效的栈操作序列,则经过所有的入栈和出栈操作之后,每个元素各入栈和出栈一次,栈为空。
因此,可以遍历两个数组,模拟入栈和出栈操作,判断两个数组是否为有效的栈操作序列。
模拟入栈操作可以通过遍历数组 pushed 实现。由于只有栈顶的元素可以出栈,因此模拟出栈操作需要判断栈顶元素是否与 popped 的当前元素相同,如果相同则将栈顶元素出栈。由于元素互不相同,因此当栈顶元素与 popped 的当前元素相同时必须将栈顶元素出栈,否则出栈顺序一定不等于 popped。
根据上述分析,验证栈序列的模拟做法如下:
- 遍历数组 pushed,将 pushed 的每个元素依次入栈 ans;
- 每次将 pushed 的元素入栈之后,如果栈不为空且栈顶元素与 popped 的当前元素相同,则将栈顶元素出栈,同时遍历数组 popped,直到栈为空或栈顶元素与 popped 的当前元素不同。
遍历数组 pushed 结束之后。如果栈为空,则返回 true;否则,返回 false。
Java版:
class Solution {
public boolean validateStackSequences(int[] pushed, int[] popped) {
Deque<Integer> ans = new LinkedList<>();
int i = 0;
for (int p: pushed) {
ans.push(p);
while (p == popped[i]) {
ans.pop();
i += 1;
if (ans.isEmpty()) {
break;
}
p = ans.peek();
}
}
return ans.isEmpty();
}
}
Python3版:
class Solution:
def validateStackSequences(self, pushed: List[int], popped: List[int]) -> bool:
ans = []
i = 0
for p in pushed:
ans.append(p)
while p == popped[i]:
ans.pop()
i += 1
if len(ans) == 0:
break
p = ans[-1]
return len(ans) == 0
复杂度分析
- 时间复杂度:O(n),其中 n 是数组 pushed 和 popped 的长度。需要遍历数组 pushed 和 popped 各一次,判断两个数组是否为有效的栈操作序列。
- 空间复杂度:O(n),其中 n 是数组 pushed 和 popped 的长度。空间复杂度主要取决于栈空间,栈内元素个数不超过 n。