首页 > 试题广场 >

出栈顺序

[编程题]出栈顺序
  • 热度指数:642 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
已知某一个字母序列,把序列中的字母按出现顺序压入一个栈,在入栈的任意过程中,允许栈中的字母出栈,求所有可能的出栈顺序


输入描述:
字符串,如:abc


输出描述:
可能的出栈顺序,每行一种顺序
示例1

输入

abc

输出

abc
acb
bac
bca
cba
#include <bits/stdc++.h>
using namespace std;

string s;

set<string> res;  // 去重排序

void dfs(int x, string ans, string stk) {
    if (x == s.size()) {
        reverse(stk.begin(), stk.end());
        res.emplace(ans + stk);
        return;
    }
    stk += s[x];  // 把第 x 个字符入栈
    for (int i = 0; i <= stk.size(); i ++) {  // 每一步都有可能有字符出栈且可能出多个字符
        string nstk = stk.substr(0, i);  // 前 i 个字符不出栈
        string tmp = stk.substr(i, stk.size() - i);
        reverse(tmp.begin(), tmp.end());
        // 出栈的字符加到答案序列中
        dfs(x + 1, ans + tmp, nstk);
    }
}

int main() {
    cin >> s;
    dfs(0, "", "");
    for (auto i : res)
        cout << i << "\n";
}

发表于 2022-08-31 02:33:51 回复(0)
使用递归,完成后使用sort进行排序(这里居然不是只要结果一样就行,还要求顺序)
#include <stack>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;

string str;
stack<char> st;
vector<char> vec;
vector<string> ans;

void solve(int index)
{
	if (index == str.size())
	{
		if (!st.empty())
		{
			char e = st.top();
			st.pop();
			vec.push_back(e);
			solve(index);
			vec.pop_back();
			st.push(e);
		}
		else
		{
			ans.push_back(string(vec.begin(), vec.end()));
		}
	}
	else
	{
		st.push(str[index]);
		solve(index + 1);
		st.pop();

		if (!st.empty())
		{
			char e = st.top();
			st.pop();
			vec.push_back(e);
			solve(index);
			vec.pop_back();
			st.push(e);
		}
	}
	
}

bool cmp(string a, string b)
{
	return a < b;
}
int main()
{
	cin >> str;
	solve(0);
	sort(ans.begin(), ans.end(), cmp);

	for (auto & s : ans)
	{
		cout << s << endl;
	}
	return 0 ;
}


发表于 2022-03-04 15:43:08 回复(1)
#include <stdio.h>
 
 
typedef struct _c_node{
    char data;
    struct _c_node* next;
} c_node;
 
 
c_node* c_node_pop(c_node* p_head)
{
    c_node* res = p_head->next;
    p_head->next = p_head->next->next;
    return res;
}
 
void c_node_stack(c_node* p_head, c_node* p_node)
{
    p_node->next = p_head->next;
    p_head->next = p_node;
}
 
int c_node_len(c_node* p_head)
{
    int len=0;
    c_node* p_next = p_head->next;
    while(p_next){
        len++;
        p_next = p_next->next;
    }
    return len;
}
 
void c_node_add_to_last(c_node* p_head, c_node* p_node)
{
    c_node* p_next = p_head->next;
    while(1){
        if(!p_next){
            p_head->next = p_node;
            p_node->next = NULL;
            return;
        }
        if(p_next->next){
            p_next = p_next->next;
        }else{
            p_next->next = p_node;
            p_node->next = NULL;
            return;
        }
    }
}
 
c_node* c_node_pop_last(c_node* p_head)
{
    c_node* p_next = p_head->next;
    c_node* res;
 
    if(!p_next->next){
        p_head->next = NULL;
        return p_next;
    }
    while(p_next->next->next){
        p_next = p_next->next;
    }
    res = p_next->next;
    p_next->next = NULL;
    return res;
}
 
 
void walker(c_node* p_raw, c_node* p_stack, c_node* p_print)
{
    c_node* p_next = p_print->next;
    if(c_node_len(p_raw) == 0 && c_node_len(p_stack) == 0){
        while(p_next){
            printf("%c", p_next->data);
            p_next = p_next->next;
        }
        printf("\n");
    }else if(c_node_len(p_raw) == 0){
        c_node_add_to_last(p_print, c_node_pop(p_stack));
        walker(p_raw, p_stack, p_print);
        c_node_stack(p_stack, c_node_pop_last(p_print));
 
    }else if(c_node_len(p_stack) == 0){
        c_node_stack(p_stack, c_node_pop(p_raw));
        walker(p_raw, p_stack, p_print);
        c_node_stack(p_raw, c_node_pop(p_stack));
    }else{
        c_node_add_to_last(p_print, c_node_pop(p_stack));
        walker(p_raw, p_stack, p_print);
        c_node_stack(p_stack, c_node_pop_last(p_print));
         
        c_node_stack(p_stack, c_node_pop(p_raw));
        walker(p_raw, p_stack, p_print);
        c_node_stack(p_raw, c_node_pop(p_stack));
 
    }
}
 
int main()
{
    char ch;
    char str[1000] = {0};
    c_node head_raw, head_stack, head_print;
 
    while(scanf("%s", &str) != EOF){
        head_raw.next = NULL;
        head_stack.next = NULL;
        head_print.next = NULL;
 
 
        for(int i=0; str[i] != 0; i++){
            c_node* new_node = malloc(sizeof(c_node));
            new_node->data = str[i];
            c_node_add_to_last(&head_raw, new_node);
        }
 
        walker(&head_raw, &head_stack, &head_print);
 
        for(int i=0; i<1000; i++){
            str[i] = 0;
        }
    }
 
}
对比了其他答案,做题用c可真麻烦,但也实在不想学c++,无奈。
思路:用链表实现栈结构,然后函数递归来实现遍历。
遍历过程有两种方式,一种是每一个分支都对全部栈进行拷贝,然后将副本传递给下一层的函数。另一种是像这里一样,所有分支都共用一套栈,每从一层弹出时都恢复一步,选择这种的原因只是懒得写free,考虑到题目的数据规模不大,甚至连创建的初始链表节点我都懒得写free,没什么做题经验,时间实在太不够了。
最后还要吐槽,答案必须按照顺序输出才有用,即“尽量先清空栈,先将字符转移到输出列”的这个顺序,若按“优先将字符全部放入栈,最后才转移到输出列”的顺序,则只会对一题
编辑于 2021-09-23 03:13:50 回复(0)
#include <bits/stdc++.h>
using namespace std;

string str;
vector<bool> st;
vector<int> arr;

int n;
// 检查当前出栈方式是否合法
bool check(vector<int>& arr) {
    stack<char> st;
    int j = 0;
    // 遍历入栈顺序
    for(int i = 0; i < n; ++i) {
        st.push(str[i]);
        while(st.size() && st.top() == str[arr[j]]) {
            st.pop(); j ++;
        }
    }
    return st.empty();
}
void dfs(int x) {
    if (x >= n) {
        if (check(arr)) {
            for (int i = 0; i < str.size(); ++ i) {
                cout << str[arr[i]];
            }
            cout << endl;
        }
        return ;
    }
    for (int i = 0; i < n; ++ i) {
        if (!st[i]) {
            st[i] = true;
            arr[x] = i;
            dfs(x + 1);
            st[i] = false;
            arr[x] = 0;
        }
    }
}

int main() {
    cin >> str; n = str.size();
    st.resize(n); arr.resize(n);
    dfs(0);
    return 0;
}
发表于 2024-10-15 11:33:41 回复(1)

回溯

用字符串t存储出栈顺序,当t刚好把所有出栈元素都装下时(t的长度为输入的字符串长度,栈为空),说明找到了一个答案,输出。

#include <iostream>
#include <string>
#include <stack>
using namespace std;

string s, t;
stack<char> stk;

void dfs(int i)
{
    // 如果所有字符都已经处理完,并且栈也为空,输出当前的出栈序列
    if (i == s.size() && stk.empty())
    {
        cout << t << endl;
        return;
    }

    // pop:当栈中有元素时,可以尝试出栈操作
    if (!stk.empty())
    {
        char x = stk.top();  // 获取栈顶元素
        stk.pop();           // 出栈
        t.push_back(x);      // 将出栈元素加入结果序列
        dfs(i);              // 递归继续
        t.pop_back();        // 回溯,恢复状态
        stk.push(x);         // 回溯,恢复栈的状态
    }

    // push:当还有未处理的字符时,可以尝试入栈操作
    if (i < s.size())
    {
        stk.push(s[i]);  // 将字符入栈
        dfs(i + 1);      // 递归处理下一个字符
        stk.pop();       // 回溯,恢复栈的状态
    }
}

int main()
{
    cin >> s;
    dfs(0);    // 从第一个字符开始递归处理,才符合题目输出要求
    return 0;
}
发表于 2024-09-13 15:59:56 回复(0)
#include<bits/stdc++.h>
using namespace std;

void dfs(string str,string pin,int idx, stack<char> sta,vector<string>& ans) {
    if (idx == str.size()) {
        while(!sta.empty()) {
            char a= sta.top();
            sta.pop();
            pin += a;
        }
        ans.push_back(pin);
        return;
    }

    sta.push(str[idx]);//每次都入栈,
    dfs(str, pin, idx + 1, sta,ans);//当前不出
    while (!sta.empty()) {//dfs每次出
        char a = sta.top();
        sta.pop();
        pin += a;
        dfs(str, pin, idx + 1, sta,ans);
    }

}
vector<string> solve(string str) {
    vector<string> ans;
    stack<char> sta;
    string pin = "";
    dfs(str, pin, 0, sta,ans);
    return ans;
}

int main()
{
    string str;
    cin >> str;
    vector<string> b = solve(str);
    sort(b.begin(), b.end());
    cout << b[0] << "\n";
    for (int i = 1; i < b.size(); i++) {
        if (b[i] != b[i-1]) {//消重
            cout << b[i] << "\n";
        }
    }
    return 0;
}

发表于 2022-04-14 20:56:56 回复(0)
提供一种DFS状态模拟思路(大佬轻喷)
#include<iostream>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std;
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);

    }  
}
int main()
{
    queue<char> q1,q2;
    stack<char> stk;
    string str;
    cin>>str;
    for(int i=0;i<str.size();i++)
    {
        q1.push(str[i]); 
    }
    dfs(q1,stk,q2);
    sort(ans.begin(),ans.end());
    for(auto it:ans)
        cout<<it<<endl;
}


发表于 2020-10-17 01:11:48 回复(0)
#include <iostream>
#include <stack>
#include <vector>
using namespace std;
 
bool checkStackOutLegal(string stackIn, int lenIn, vector<char> stackOut, int lenOut)
{
    if(stackIn=="" | stackOut.empty())
        return false;
    if(lenIn!=lenOut)
        return false;
    stack<char> s;
    int j=0;
    for(int i=0;i<stackIn.size();i++)
    {
        s.push(stackIn[i]);
        while(s.size()>0 && s.top()==stackOut[j])
        {
            s.pop();
            ++j;
        }
    }
    return s.size()>0? false:true;
}
 
void fullPermutation(string a, int left, int right, vector<vector<char>> &v)
{
   if(left==right)
   {
       vector<char> one;
       for(int i=0;i<right;i++)
       {
           one.push_back(a[i]);
       }
       v.push_back(one);
   }
    else
    {
        for(int i=left;i<right;i++)
        {
            swap(a[i],a[left]);
            fullPermutation(a, left+1, right, v);
            swap(a[i], a[left]);
        }
    }
}
 
int main()
{
    string str;
    cin>>str;
    int len=str.size();
     
    vector<vector<char>> v;
    fullPermutation(str, 0, len, v);
     
    for(int i=0;i<v.size();i++)
    {
        if(checkStackOutLegal(str, len, v[i], len))
        {
            for(int j=0;j<v[i].size();j++)
            {
                cout<<v[i][j];
            }
            cout<<endl;
        }
    }
 
    return 0;
}

发表于 2020-08-24 17:51:24 回复(0)
/*
1 首先找出入栈序列的全排列,将全排列存到 vector<string> iv 里
2 然后去遍历iv里的输出序列,判断其其是否为栈的输出序列
3 最后将符合条件的输出序列存在 vector<string> res_iv 里,进行字典排序后打印输出
*/
#include <iostream>
#include <vector>
#include <stack>
#include <string>
#include <algorithm>
using namespace std;
void my_swap(char& ch1, char& ch2) {
 char temp = ch1 ^ ch2;
 ch1 ^= temp;
 ch2 ^= temp;
}
void get_all_order(char* str, int left, int n, vector<string>& iv) {
 if (n-left < 1) {
  iv.push_back(str);
  return;
 }
 for (int i = left; i < n; ++i) {
  my_swap(str[left], str[i]);
  get_all_order(str, left + 1, n, iv);
  my_swap(str[left], str[i]);
 }
}
bool is_pop_order(string& push_str, string& pop_str) {
 int n = push_str.size();
 if (n < 2)
  return true;
 stack<char> sk1;
 char temp;
 int j = 0;
 for (int i = 0; i < n; ++i) {
  temp = pop_str[i];
  while (sk1.empty() || sk1.top() != temp) {
   sk1.push(push_str[j]);
   ++j;
   if (j > n)
    return false;
  }
  if (!sk1.empty())
   sk1.pop();
 }
 return true;
}
int main() {
 string str;
 vector<string> iv;
 vector<string> res_iv;
 cin >> str;
 
 auto temp = str.c_str();
 get_all_order(const_cast<char*>(temp), 0,str.size(), iv);
 for (auto it = iv.begin(); it != iv.end(); ++it)
  if (is_pop_order(str, *it))
   res_iv.push_back(*it);
 sort(res_iv.begin(), res_iv.end());
 for (auto it = res_iv.begin(); it != res_iv.end(); ++it)
  cout << *it << endl;
 return 0;
}

发表于 2020-06-14 15:15:45 回复(1)
#include <iostream>
#include <string>
#include <vector>
#include <set>
using namespace std;
int main() {
    string str;
    cin >> str;
    vector<pair<string, string>> result;    //(栈中字符,出栈字符)
    result.push_back({ string(),string() });
    for (const char& ch : str) {
        int m_size = result.size();
        for (int i = 0; i < m_size; i++) {
            result[i].first.push_back(ch); 
            pair<string, string> temp = result[i];
            for (int j = 0; j < result[i].first.size(); j++) {
                temp.second.push_back(temp.first.back());
                temp.first.pop_back();
                result.push_back(temp);
            }
        }
    }
    set<string> output;
    for (auto& stk : result)
        output.insert(stk.second + string(stk.first.rbegin(), stk.first.rend()));
    for (const string& str : output)
        cout << str << endl;
    return 0;
}

发表于 2020-06-05 19:49:00 回复(0)