剑指offer Leetcode 46,47 字符串的排列 全排列问题(通用解法)

1.1 题目描述

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

1.2 解题思路

对于全排列问题,不论是字符串的全排列还是数字的全排列,都可以采用回溯法来解决。
核心思想是我们每次递归只确定一个数字的位置。也就是说我们首先固定索引为0的数字,之后我们确定索引为1的数字,一直递归下去,直到整个字符串都被确定那么就得到了全排列的一种排列。

1.3 全排列中的字符不重复 (leetcode 46)

对于不重复的情况比较简单,比如 abc的全排列不会出现重复的情况。代码如下

class Solution {
public:
    vector<string> Permutation(string str) {
        if(str.size()<=0)
            return {};
        vector<string> res;
        dfs(res,str,0);
        return res;
    }
    
    void dfs(vector<string>& res,string & str,int start)
    {
        if(start == str.size()-1)
        {
            res.push_back(str);
            return;
        }
        for(int i=start;i<str.size();i++)
        {
            swap(str[i],str[start]);
            dfs(res,str,start+1);
            swap(str[i],str[start]);
        }
    }
};

1.4 全排列中包含重复的字符(leetcode 47)

在1.3中给出了全排列的解法,但是对于字符串是‘aa’这种情况,上述解法会得到[‘aa’,‘aa’]也就是会出现重复的情况,因此我们需要对此改进,改进方法也非常简单。 我们需要先对字符串进行排序,之后我们对其进行剪枝操作。

class Solution {
public:
    vector<string> Permutation(string str) {
        if(str.size()<=0)
            return {};
        vector<string> res;
        sort(str.begin(),str.end());   先进行排序保证剪枝操作是正确的
        dfs(res,str,0);
        sort(res.begin(),res.end());   保证字典序
        return res;
    }
    
    void dfs(vector<string>& res,string&  str,int start)
    {
        if(start == str.size()-1)
        {
            res.push_back(str);
            return;
        }
        for(int i=start;i<str.size();i++)
        {
            if(i>start && str[i] == str[start])   剪枝操作
                continue;
            swap(str[i],str[start]);
            dfs(res,str,start+1);
            swap(str[i],str[start]);
        }
    }
};
发布了17 篇原创文章 · 获赞 17 · 访问量 453

猜你喜欢

转载自blog.csdn.net/weixin_42134034/article/details/105564831
今日推荐