0946-验证栈序列

Raphael Liu Lv10

给定 pushedpopped 两个序列,每个序列中的 值都不重复 ,只有当它们可能是在最初空栈上进行的推入 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
  • poppedpushed 的一个排列

方法一:栈模拟

这道题需要利用给定的两个数组 pushed 和 popped 的如下性质:

  • 数组 pushed 中的元素互不相同;

  • 数组 popped 和数组 pushed 的长度相同;

  • 数组 popped 是数组 pushed 的一个排列。

根据上述性质,可以得到如下结论:

  • 栈内不可能出现重复元素;

  • 如果 pushed 和 popped 是有效的栈操作序列,则经过所有的入栈和出栈操作之后,每个元素各入栈和出栈一次,栈为空。

因此,可以遍历两个数组,模拟入栈和出栈操作,判断两个数组是否为有效的栈操作序列。

模拟入栈操作可以通过遍历数组 pushed 实现。由于只有栈顶的元素可以出栈,因此模拟出栈操作需要判断栈顶元素是否与 popped 的当前元素相同,如果相同则将栈顶元素出栈。由于元素互不相同,因此当栈顶元素与 popped 的当前元素相同时必须将栈顶元素出栈,否则出栈顺序一定不等于 popped。

根据上述分析,验证栈序列的模拟做法如下:

  1. 遍历数组 pushed,将 pushed 的每个元素依次入栈;

  2. 每次将 pushed 的元素入栈之后,如果栈不为空且栈顶元素与 popped 的当前元素相同,则将栈顶元素出栈,同时遍历数组 popped,直到栈为空或栈顶元素与 popped 的当前元素不同。

遍历数组 pushed 结束之后,每个元素都按照数组 pushed 的顺序入栈一次。如果栈为空,则每个元素都按照数组 popped 的顺序出栈,返回 true。如果栈不为空,则元素不能按照数组 popped 的顺序出栈,返回 false。

[sol1-Python3]
1
2
3
4
5
6
7
8
9
class Solution:
def validateStackSequences(self, pushed: List[int], popped: List[int]) -> bool:
st, j = [], 0
for x in pushed:
st.append(x)
while st and st[-1] == popped[j]:
st.pop()
j += 1
return len(st) == 0
[sol1-Java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
public boolean validateStackSequences(int[] pushed, int[] popped) {
Deque<Integer> stack = new ArrayDeque<Integer>();
int n = pushed.length;
for (int i = 0, j = 0; i < n; i++) {
stack.push(pushed[i]);
while (!stack.isEmpty() && stack.peek() == popped[j]) {
stack.pop();
j++;
}
}
return stack.isEmpty();
}
}
[sol1-C#]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Solution {
public bool ValidateStackSequences(int[] pushed, int[] popped) {
Stack<int> stack = new Stack<int>();
int n = pushed.Length;
for (int i = 0, j = 0; i < n; i++) {
stack.Push(pushed[i]);
while (stack.Count > 0 && stack.Peek() == popped[j]) {
stack.Pop();
j++;
}
}
return stack.Count == 0;
}
}
[sol1-C++]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public:
bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {
stack<int> st;
int n = pushed.size();
for (int i = 0, j = 0; i < n; i++) {
st.emplace(pushed[i]);
while (!st.empty() && st.top() == popped[j]) {
st.pop();
j++;
}
}
return st.empty();
}
};
[sol1-C]
1
2
3
4
5
6
7
8
9
10
11
12
13
bool validateStackSequences(int* pushed, int pushedSize, int* popped, int poppedSize){
int *stack = (int *)malloc(sizeof(int) * pushedSize);
int top = 0;
for (int i = 0, j = 0; i < pushedSize; i++) {
stack[top++] = pushed[i];
while (top > 0 && stack[top - 1] == popped[j]) {
top--;
j++;
}
}
free(stack);
return top == 0;
}
[sol1-JavaScript]
1
2
3
4
5
6
7
8
9
10
11
12
var validateStackSequences = function(pushed, popped) {
const stack = [];
const n = pushed.length;
for (let i = 0, j = 0; i < n; i++) {
stack.push(pushed[i]);
while (stack.length && stack[stack.length - 1] == popped[j]) {
stack.pop();
j++;
}
}
return stack.length === 0;
};
[sol1-Golang]
1
2
3
4
5
6
7
8
9
10
11
12
func validateStackSequences(pushed, popped []int) bool {
st := []int{}
j := 0
for _, x := range pushed {
st = append(st, x)
for len(st) > 0 && st[len(st)-1] == popped[j] {
st = st[:len(st)-1]
j++
}
}
return len(st) == 0
}

复杂度分析

  • 时间复杂度:O(n),其中 n 是数组 pushed 和 popped 的长度。需要遍历数组 pushed 和 popped 各一次,判断两个数组是否为有效的栈操作序列。

  • 空间复杂度:O(n),其中 n 是数组 pushed 和 popped 的长度。空间复杂度主要取决于栈空间,栈内元素个数不超过 n。

 Comments
On this page
0946-验证栈序列