已知某一个字母序列,把序列中的字母按出现顺序压入一个栈,在入栈的任意过程中,允许栈中的字母出栈,求所有可能的出栈顺序。
例如:
入栈顺序:
abc
其所有可能出栈顺序。
abc
acb
bac
bca
cba
【思路一】
状态转移+DFS模拟出所有操作:
容易知道一个状态包含以下三部分:
常见的状态转移过程:
- q1为空 stack为空 =》那么所有元素都已经出栈,输出出栈序列,为终止状态
- q1为空 stack不为空 =》那么只能出栈
- q1不为空 stack为空 =》 入栈一个元素=》转移到下一个状态
- q1不为空 stack不为空 =》入栈一个元素或者出栈一个元素=》转移到下一个状态(多入口dfs)
vector<string> ans;
void dfs(queue<char> q1,stack<char> stk,queue<char> q2)
{
if(q1.empty() && stk.empty()) //如果全部都出栈了
{
string str;
while(!q2.empty())
{
str+=q2.front();
q2.pop();
}
ans.push_back(str);
return;
}
if(!q1.empty()) //如果还有没有入栈的
{
if(!stk.empty()) //同时栈中也有元素 那么有两种选择
{
//第一种 入栈一个元素
queue<char> q_temp=q1;
stack<char> stk_temp=stk;
char c=q_temp.front();
q_temp.pop();
stk_temp.push(c);
dfs(q_temp,stk_temp,q2);
//或者 出栈一个元素
c=stk.top();
stk.pop();
q2.push(c);
dfs(q1,stk,q2);
}
else
{
//入栈一个元素
char c=q1.front();
q1.pop();
stk.push(c);
dfs(q1,stk,q2);
}
}
else
{
//出栈一个元素
char c=stk.top();
stk.pop();
q2.push(c);
dfs(q1,stk,q2);
}
}
【思路二】
全排列+验证合法
先求出原先序列的全排列:
交换法实现全排列:
void dfs(string str,int left,int right,vector<string>& ans)
{
if(left==right)
{
ans.push_back(str);
return;
}
for(int i=left;i<right;i++)
{
swap(str[left],str[right]);
dfs(str,left+1,right,ans);
swap(str[left],str[right]);
}
}
验证全排列的每一个序列是否可能为出栈序列:
bool fun(string str1,string str2)
{
if(str1.size()!=str2.size())
return false;
stack<char> stk;
int j=0;
for(int i=0;i<str1.size();i++)
{
stk.push(str1[i]);
while(!stk.empty() && stk.top()==str2[j]) //判断栈顶是否为 当前需要出栈序列元素
{
stk.pop(); //是的话不断弹出 while是关键
j++;
}
//其它情况 压人元素
}
return j==str2.size(); //判断是否弹出 str2.size()个
}
最后对结果,作一个字典序排序输出即可