• A--1-数据结构(6)--字符串全排列和子序列问题


    题目1 字符串全排列问题

    两种去重的方式

    1. 在for循环挑首字母的时候
    2. 在得到不去重的全排列之后,最后要答案的时候
    #include <iostream>
    #include <string>
    #include <vector>
    #include <set>
    using namespace std;
    vector<string> permutation(string s);
    void process(string &s, vector<string>& ans, string path);
    
    vector<string> permutation(string s)
    {
        vector<string> ans;
        if (s.empty())
        {
            return ans;
        }
        process(s, ans, " ");
        return ans;
    }
    
    /*  
        @param1 string s : 待选的字符集合
        @param2 ans: 最后的全排列
        @param3 path: 路径
    */
    void process(string &s,  vector<string>& ans, string path)
    {
        //  base case : string 里面没有可供选择的字符了,就把拼接好的path返回
        if (s.empty())
        {
            ans.push_back(path);
            return;
        }
    
        set<string> picked ;
    
        // 遍历s里面的每个字符
        // 表示的是,分别先选择出s里面的每个字符
        for (int i = 0; i < s.size(); ++i)
        {
            // 当前已将挑过的字符都放在picked里 
            // 如果这个字符已经挑过了,就跳过去了
            if ( ! picked.count (s.substr(i,1)) )
            {
                // 选择当前字符,加到path上,得到 pick
                string pick = path + s.substr(i, 1);
                picked.insert(s.substr(i, 1));
                // 得到下一次选择的字符集合 next
                // s 集合不能改啊,for循环还没结束呢
                string next(s);
                next.erase(i, 1);
                // 在选择了一个字符的情况下,再递归调用process,选择下一个字符
                process(next, ans, pick);
            }
        }
    }
    
    int main()
    {
        string ss = "aabc";
        // 调用全排列的函数
        vector<string> ans = permutation(ss);
        cout << ans.size() << endl;
        for (auto i : ans)
        {
            cout << i << endl;
        }
        return 0;
    }
    
    class Solution {
    public:
        vector<string> permutation(string s) {
            vector<string> res;
            string path;
            set <string> picked;
            if (s.empty())
            {
                return res;
            }
            process( res , s , path , picked);
            return res;
        }
    
        // @param1  vector<string>& ans  存储全排列的字符串
        // @param2  string& sets    可选的字符串
        // @param3  string& path    路径
        // @param4  set <string>& picked 去重
        void process( vector<string>& ans , const string& sets , string& path , set <string>& picked )
        {
            // base case : 可选的字符串没了
            if ( sets.size() == 0 )
            {
                // 重复了,就直接返回
                if ( picked.count(path) )
                {
                    return ;
                }
                ans.push_back(path);
                picked.insert(path);
                return ;
            }
            //  sets里每位置的字符做path[0],分别递归
            for ( int i = 0 ; i < sets.size(); ++i)
            {
                // 对于每个开头,都是一个新的path, 因此不能累加
                string path_i = path + sets.substr( i ,1 );
                // 对于每个开头,sets都不能变, 因此要复制一下
                string next_sets (sets);
                next_sets.erase(i,1);
                process( ans , next_sets , path_i ,picked );
            }
        }
    };
    
    题目2 打印字符串的全部子序列

    典型的从左向右的递归
    在每个位置决定要还是不要!

    #include <iostream>
    #include <set>
    #include <vector>
    using namespace std;
    
    void process(string str, int index, string path, vector<string> &ans);
    vector<string> allSubseq(string str);
    
    vector<string> allSubseq(string str)
    {
        vector<string> ans ; 
        if( str.size() == 0 )
        {
            ans.push_back(" ");
            return ans;
        }
        // 调用递归辅助函数
        process(str , 0 , " " ,ans );
        return ans; 
    }
    
    // str[0...index-1]的沿途决定(要或是不要),用string path记录
    // 所有的子序列都放到 ans 中
    void process( string str , int index , string path, vector<string>& ans )
    {
        // base_case : 当遍历完当前容器,把 path 加入到 ans 里
        if( index == str.size() ){
            ans.push_back(path);
        }else{
            // 当前位置的字符不加入路径->处理下一个位置的字符
            process(str,index+1,path,ans);
            // 当前位置的字符加入路径->处理下一个位置的字符
            process(str, index + 1, path + str[index], ans);
        }
    }
    
    int main()
    {
        string ss = "abc";
        vector<string> ans = allSubseq(ss);
        cout << ans.size() << endl;
        for (auto i : ans)
        {
            cout << i << endl;
        }
        return 0;
    }
    
    干啥啥不行,吃饭第一名
  • 相关阅读:
    7-3 列表或元组的数字元素求和 (20 分)
    7-2 一帮一 (15 分)
    7-11 字典合并 (40 分)
    7-6 统计工龄 (20 分)
    7-5 统计字符出现次数 (20 分)
    7-4 分析活动投票情况 (20 分)
    7-3 四则运算(用字典实现) (30 分)
    7-22 找鞍点 (20 分)
    制作 U 盘启动盘
    mysql 多表连接的
  • 原文地址:https://www.cnblogs.com/jiangxinyu1/p/12407692.html
Copyright © 2020-2023  润新知