一、基础问题:怎么判断弹出序列是否合法?
先从一道经典算法题入手,题目描述如下:
输入两个整数序列,第一个是栈的压入顺序(所有数字不重复),请判断第二个序列是否可能是该栈的弹出顺序。 示例 1:压入 [1,2,3,4,5],弹出 [4,5,3,2,1] → 合法(返回 true) 示例 2:压入 [1,2,3,4,5],弹出 [4,3,5,1,2] → 不合法(返回 false)
1.1 常规解法:模拟栈操作
最直观的思路是'复现'栈的压入和弹出过程,步骤很简单:
- 遍历压入序列,把元素逐个压入栈;
- 每次压入后,检查栈顶元素是否和当前弹出序列的'待弹出元素'(用指针标记)一致;
- 如果一致,就弹出栈顶,并移动弹出指针;
- 遍历结束后,若栈为空,说明所有元素都按顺序弹出,序列合法;否则不合法。
代码实现(C++)
#include <vector>
#include <stack>
using namespace std;
bool IsPoporder(vector<int>& pushV, vector<int>& popV) {
size_t popIdx = 0;
stack<int> st;
for (auto& num : pushV) {
st.push(num);
while (!st.empty() && st.top() == popV[popIdx]) {
st.pop();
popIdx++;
}
}
return st.empty();
}
1.2 模拟过程示意图
以示例 1 压入 [1,2,3,4,5],弹出 [4,5,3,2,1] 为例,展示每一步的变化:
| 步骤 | 压入元素 | 栈内元素 | 弹出指针 popIdx | 栈顶是否匹配 popV[popIdx] | 操作后栈内元素 | 操作后 popIdx |
|---|---|---|---|---|---|---|
| 1 | 1 | [1] | 0 | 1≠4 → 不匹配 | [1] |


