笔记 | P4387 【深基15.习9】验证栈序列 题解

题解

问题描述

给出两个序列 pushedpoped,分别表示入栈和出栈操作的顺序。我们需要判断给定的出栈序列是否可能对应于给定的入栈序列。如果可能,则输出 “Yes”;否则,输出 “No”。

解题思路

  1. 读取输入:读取询问次数 q 和每次询问的入栈和出栈序列。

  2. 模拟栈操作:通过使用一个栈(s1)和一个队列(s2),我们可以模拟栈的入栈和出栈操作。
    a. 入栈操作:按顺序遍历入栈序列 pushed,每次将元素推入栈 s1
    b. 出栈操作:每次入栈后,检查栈顶元素是否与队列 s2 的前端元素相匹配。如果匹配,则从栈和队列中弹出元素,并继续检查下一个元素,直到不匹配或栈为空。

  3. 检查结果:如果所有出栈元素都被成功弹出,则输出 “Yes”。否则,输出 “No”。

  4. 清理数据结构:为下一次查询准备,确保栈和队列为空。

原始代码的错误

原始代码中的错误在于缺乏对连续出栈操作的处理。在模拟过程中,可能存在连续几个元素需要出栈的情况,但原始代码在每次入栈后只执行了一次出栈操作。这意味着对于某些入栈和出栈序列组合,代码可能在执行完所有的入栈操作后仍然留有未匹配的出栈元素。

错误代码部分:

for(int i=0;i<n;i++) {
    s1.push(pushed[i]);
    if(!s1.empty() && s1.top() == s2.front()) {
        s2.pop();
        s1.pop();
    }
}

修正

修正代码主要在于增加一个内部循环,其实是把原先 if 语句改成 while 循环,用于在每次入栈后连续检查栈顶元素与队列头部元素的匹配,直到不匹配或栈为空。

修正的代码块:

for(int i=0;i<n;i++) {
    s1.push(pushed[i]);
    while(!s1.empty() && s1.top() == s2.front()) {
        s2.pop();
        s1.pop();
    }
}

复杂度分析

时间复杂度:O(n),空间复杂度:O(n)。

代码简洁化

经过这一修正,原始代码中的第二个 while 循环成为多余,并被删除。最终的代码版本更精简,也更符合问题描述中的逻辑。

最终版本的完整代码:

#include
using namespace std;
int pushed[100005];
int poped[100005];
stack<int> s1;
queue<int> s2;
int main() {
	int q;
	cin>>q;
	while(q--) {
		int n;
		cin>>n;
		for(int i=0;i<n;i++) {
			cin>>pushed[i];
		}
		for(int i=0;i<n;i++) {
			cin>>poped[i];
			s2.push(poped[i]);
		}

		for(int i=0;i<n;i++) {
			s1.push(pushed[i]);
			while(!s1.empty() && s1.top() == s2.front()) {
				s2.pop();
				s1.pop();
			}
		}

		if(s1.empty())
			cout<<"Yes"<<endl;
		else
			cout<<"No"<<endl;

		while(!s1.empty()) s1.pop();
		while(!s2.empty()) s2.pop();
	}
	return 0;
}

这个版本的代码更精简,也更符合问题描述中的逻辑。

你可能感兴趣的:(笔记,算法,c++)