牛客网_剑指offer_字符串的排列

34 篇文章 0 订阅
34 篇文章 0 订阅

题目描述

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
输入描述:
输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。

解题思路

1.利用递归的思想解题

在这里分为len步考虑,从第一个单词开始,考虑第一个位置可能出现的所有单词的情况,需要将第一个单词与后面所有位置的单词依次对换位置,也就是说本来是[1, 2, 3]。在这个基础上,对调完了有两个三个情况,[1, 2, 3], [2, 1, 3],[3, 2, 1]
然后在所有的结果中对应求第二个位置的所有的可能的情况,依此递归。
具体代码如下(这里利用的是递归的思想,但是实现的时候摒弃了递归的写法,因为递归是一个速度比较慢的方法,能避则避):

class Solution 
{

public:
    vector<string> Permutation(string str) 
    {
        //问题在于怎么遍历所有情况,也就是怎么得到一个1到str.size()的排列
        //思路:使用递归思想
        vector<string> res{};
        vector<string> tmp{};
        int len = str.size();
        if (str.size() == 0) return res;
        res.push_back(str);
        
        for (int i = 0; i < len; i++)
        {
            res = my_func(res, i, len);
        }
        return res;
    }
    
    vector<string> my_func(vector<string> string_set, int idx, int len)
    {
        vector<string> res{};
        string tmp;
        for(auto str : string_set)
        {
            tmp = str;
            for (int i = idx; i < len; i++)
            {
                auto tmp_ch = tmp[idx];
                tmp[idx] = tmp[i];
                tmp[i] = tmp_ch;
                if (find(res.begin(), res.end(), tmp) == res.end() && tmp.size() != 0) res.push_back(tmp);
            }
        }
        return res;
    }
};

2.求出所有的可能的路径
如果字符串长度为len,则分len步去做,第n步的作用为找到所有的前n步的可能的情况,也就是说,假设len为4,则第一步的可能为0, 1, 2, 3。第二步的可能就是在第一步的基础上加一步,加的新的步骤必须是之前未出现的元素,例如以0为第一步的情况下,可能的结果为[0, 1],[0, 2],[0,3],根据这样的方法,找到所有的可能的0到len-1的排列,对应的找到其字符串即可(由于可能有字符重复,所以需要考虑重复的情况,在向最终结果导入字符串的时候做一次判断即可)。

具体代码如下:

class Solution 
{
    vector<vector<int> > paths{};
    vector<int> path{};
public:
    vector<string> Permutation(string str) 
    {
        //问题在于怎么遍历所有情况,也就是怎么得到一个1到str.size()的排列
        //思路:为了得到所有的路径,就化为str.size()个步骤的遍历即可
        vector<vector<int> > res{};
        vector<string> ans{};
        int len = str.size();
        
        
        for (int i = 0; i < len; i++)
        {
            res = get_next_set(res, len);
        }
        
        string my_str;
        for (auto x : res)
        {
            my_str.clear();
            for (auto idx : x)
            {
                my_str.push_back(str[idx]);
            }
            if (find(ans.begin(), ans.end(), my_str) == ans.end()) ans.push_back(my_str);
        }
        
        return ans;
    }
    
    vector<vector<int> > get_next_set(vector<vector<int> > my_set, int len)
    {
        vector<vector<int> > res{};
        vector<int> tmp{};
        if (my_set.empty())
        {
            for (int i = 0; i < len; i++)
            {
                tmp.clear();
                tmp.push_back(i);
                res.push_back(tmp);
            }
        }
        else
        {
            for (auto set : my_set)
            {
                for (int i = 0; i < len; i++)
                {
                    if (find(set.begin(), set.end(), i) == set.end())
                    {
                        tmp = set;
                        tmp.push_back(i);
                        res.push_back(tmp);
                    }
                }
            }
        }
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值