剑指offer第二十七题字符串的排列

题目描述

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。

输入描述:

输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。

题目分析

题目中要求字符串的全排列,但是重点是如何用字典序输出,这样的题目有投机取巧的做法,就是用STL的首先必然是利用库函数next_permutation来做,然后set去重。但是这样好像失去了题目的意义。递归的做可以将三个字母看着两个字母,将后面两个字母绑在一起按照第一个字符去跟后面的交换,递归即可以解决,现在可以使用非递归的方法解决。思想与递归类似

方法一:用库函数做

vector<string> Permutation(string str) {
        vector<string> answer;
        if(str.empty())
            return answer;       
        sort(str.begin(),str.end());
        do{
            answer.push_back(str);
        }
        while(next_permutation(str.begin(),str.end()));
        return answer;
}

方法二:用Python做

class Solution:
    def Permutation(self, ss):
        # write code here
        res = []
        if len(ss) < 2:
            return ss.split()
        for i in range(len(ss)):
            for n in map(lambda x: x+ ss[i], self.Permutation(ss[:i]+ss[i+1:])):
                if n not in res:
                    res.append(n)
        return sorted(res)

方法三:剑指offer

class Solution {
public:
    void PermutationHelp(vector<string> &ans, int k, string str) //遍历第k位的所有可能
{
    if(k == str.size() - 1)
        ans.push_back(str);
    unordered_set<char> us;  //记录出现过的字符
    sort(str.begin() + k, str.end());  //保证按字典序输出
    for(int i = k; i < str.size(); i++)
    {
        if(us.find(str[i]) == us.end()) //只和没交换过的换
        {  
            us.insert(str[i]);
            swap(str[i], str[k]);
            PermutationHelp(ans, k + 1, str);
            swap(str[i], str[k]);  //复位
        }
    }
}
 
vector<string> Permutation(string str) {
    vector<string> ans;
    PermutationHelp(ans, 0, str);
    return ans;
}

};

方法三:递归dfs

class Solution {
public:
    vector<string> Permutation(string str) {       
        if(str!="") dfs(str, 0);
        return ret;
    }
private:
    vector<string> ret;
    void dfs(string str, int s){
        int sz = str.size();
        if(s==sz){
            ret.push_back(str);
            return;
        }
        for(int i = s; i < sz; ++i){
            if(i!=s && str[s]==str[i]) continue;
            swap(str[s], str[i]);
            dfs(str, s+1);
        }
    }  
};

方法四:非递归

class Solution {
public:
    vector<string> Permutation(string str) {
        typedef string::iterator _BI;
        vector<string> ret;
        _BI _F = str.begin(), _L = str.end();
        _BI _I = _L;
        if (_F == _L)
            return ret;
        if (_F == --_I) {
            ret.push_back(str);
            return ret;
        }
        ret.push_back((sort(_F, _L), str));
        for (bool f = false; !f; _I = _L, --_I) {
            for (; ; ) {
                _BI _Ip = _I;
                if (*--_I < *_Ip) {
                    _BI _J = _L;
                    for (; !(*_I < *--_J); );
                    iter_swap(_I, _J);
                    reverse(_Ip, _L);
                    ret.push_back(str);
                    break;
                }
                if (_I == _F) {
                    reverse(_F, _L);
                    f = true;
                    break;
                }
            }
        }
        return ret;
    }
};



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值