给定两个整数序列:
pushV:压栈序列popV:待验证的弹栈序列需要判断 popV 是否可能是 pushV 对应的弹栈序列。
要解决这个问题,我们需要理解栈的工作机制:
pushV 的顺序依次入栈关键洞察:我们可以通过模拟整个压栈弹栈过程来验证序列的合法性。
#include <vector>
#include <stack>
using namespace std;
class Solution {
public:
bool IsPopOrder(vector<int>& pushV, vector<int>& popV) {
// 使用辅助栈模拟压栈弹栈过程
stack<int> st;
// 双指针:_push指向当前要压入的元素,_pop指向当前要弹出的元素
size_t _push = 0; // 压栈序列的索引
size_t _pop = 0; // 弹栈序列的索引
// 遍历所有需要压入的元素
while(_push < pushV.size()) {
// 将当前元素压入栈中
st.push(pushV[_push++]);
// 检查栈顶元素是否与当前期望弹出的元素匹配
// 如果匹配,则连续弹出所有匹配的元素
while(!st.empty() && st.top() == popV[_pop]) {
_pop++; // 移动弹栈序列指针
st.pop(); // 弹出栈顶元素
}
}
// 如果所有元素都能正确弹出,栈应该为空
return st.empty();
}
};让我们通过一个具体例子来理解算法的执行过程:
示例输入:
pushV = [1, 2, 3, 4, 5]popV = [4, 5, 3, 2, 1]// 初始状态
stack<int> st; // 空栈
size_t _push = 0; // 指向元素1
size_t _pop = 0; // 指向元素4第1轮循环:
// 压入元素1
st.push(1); // 栈:[1]
_push = 1; // 指向元素2
// 检查栈顶:1 != 4,不匹配,继续第2轮循环:
// 压入元素2
st.push(2); // 栈:[1, 2]
_push = 2; // 指向元素3
// 检查栈顶:2 != 4,不匹配,继续第3轮循环:
// 压入元素3
st.push(3); // 栈:[1, 2, 3]
_push = 3; // 指向元素4
// 检查栈顶:3 != 4,不匹配,继续第4轮循环:
// 压入元素4
st.push(4); // 栈:[1, 2, 3, 4]
_push = 4; // 指向元素5
// 检查栈顶:4 == 4,匹配!
st.pop(); // 栈:[1, 2, 3]
_pop = 1; // 指向元素5第5轮循环:
// 压入元素5
st.push(5); // 栈:[1, 2, 3, 5]
_push = 5; // 超出范围
// 检查栈顶:5 == 5,匹配!
st.pop(); // 栈:[1, 2, 3]
_pop = 2; // 指向元素3
// 继续检查:3 == 3,匹配!
st.pop(); // 栈:[1, 2]
_pop = 3; // 指向元素2
// 继续检查:2 == 2,匹配!
st.pop(); // 栈:[1]
_pop = 4; // 指向元素1
// 继续检查:1 == 1,匹配!
st.pop(); // 栈:[]
_pop = 5; // 超出范围最终结果:栈为空,返回 true
// 主循环:遍历pushV中的每个元素
while(_push < pushV.size()) { // O(n)
st.push(pushV[_push++]); // O(1)
// 内层循环:每个元素最多被弹出一次
while(!st.empty() && st.top() == popV[_pop]) { // 总计O(n)
_pop++;
st.pop();
}
}stack<int> st; // 辅助栈,最坏情况下存储所有元素bool IsPopOrder(vector<int>& pushV, vector<int>& popV) {
// 如果两个序列长度不同,直接返回false
if (pushV.size() != popV.size()) {
return false;
}
// 空序列的情况
if (pushV.empty()) {
return true; // 两个空序列匹配
}
// 原算法逻辑...
}// 测试用例
vector<int> pushV = {1};
vector<int> popV = {1};
// 结果:true
vector<int> pushV2 = {1};
vector<int> popV2 = {2};
// 结果:false通过这道题的分析,我们深入理解了以下几个重要概念:
这种模拟法不仅适用于栈的相关问题,在很多其他算法场景中也有广泛应用。掌握这种思维方式,对于提升算法设计能力具有重要意义。
栈 数据结构 算法模拟 双指针 C++STL