字符串全排列

输入一个字符串如abcde按照字典序小到大打印全排列

class Solution {
public:
    vector<string> Permutation(string str) {
        //可以用递归来做
        vector<string> array;
        if(str.size()==0)
            return array;
        Permutation(array, str, 0);
        sort(array.begin(), array.end());
        return array;
    }
     
    void Permutation(vector<string> &array, string str, int begin)//遍历第begin位的所有可能性
    {
        if(begin==str.size()-1)
            array.push_back(str);
        for(int i=begin; i<=str.size()-1;i++)
        {
            if(i!=begin && str[i]==str[begin])//有重复字符时,跳过
                continue;
            swap(str[i], str[begin]);//当i==begin时,也要遍历其后面的所有字符;
                                    //当i!=begin时,先交换,使第begin位取到不同的可能字符,再遍历后面的字符
            Permutation(array, str, begin+1);//遍历其后面的所有字符;
             
            swap(str[i], str[begin]);//为了防止重复的情况,还需要将begin处的元素重新换回来
             
            /*举例来说“abca”,为什么使用了两次swap函数
                交换时是a与b交换,遍历;
                交换时是a与c交换,遍历;(使用一次swap时,是b与c交换)
                交换时是a与a不交换;
                */
        }
    }
};

下面这种对于重复的如aa  会打印多次。

 #include <bits/stdc++.h>
using namespace std;

int vis[100];
char s[100];
char ans[100];
int n;


int dfs(int deep)
{
    if (deep == 5)
    {
        printf("%s\n", ans + 1);
        return 0;
    }

    for (int i = 1; i <= n; ++i)
    {
        if (!vis[i])
        {
            vis[i] = 1;
            ans[deep] = s[i - 1];
            dfs(deep + 1);
            vis[i] = 0;
        }
    }
    return 0;
}

int main()
{
    scanf(" %s", s);
    n = strlen(s);
    sort(s, s + strlen(s));
    memset(vis, 0, sizeof(vis));
    memset(ans, 0, sizeof(ans));
    dfs(1);
    return 0;
}

迭代算法:字典生成算法

public ArrayList<String> Permutation(String str) {
       ArrayList<String> res = new ArrayList<>();
 
        if (str != null && str.length() > 0) {
            char[] seq = str.toCharArray();
            Arrays.sort(seq); //排列
            res.add(String.valueOf(seq)); //先输出一个解
 
            int len = seq.length;
            while (true) {
                int p = len - 1, q;
                //从后向前找一个seq[p - 1] < seq[p]
                while (p >= 1 && seq[p - 1] >= seq[p]) --p;
                if (p == 0) break; //已经是“最小”的排列,退出
                //从p向后找最后一个比seq[p]大的数
                q = p; --p;
                while (q < len && seq[q] > seq[p]) q++;
                --q;
                //交换这两个位置上的值
                swap(seq, q, p);
                //将p之后的序列倒序排列
                reverse(seq, p + 1);
                res.add(String.valueOf(seq));
            }
        }
 
        return res;
    }
     
    public static void reverse(char[] seq, int start) {
        int len;
        if(seq == null || (len = seq.length) <= start)
            return;
        for (int i = 0; i < ((len - start) >> 1); i++) {
            int p = start + i, q = len - 1 - i;
            if (p != q)
                swap(seq, p, q);
        }
    }
     
    public static void swap(char[] cs, int i, int j) {
        char temp = cs[i];
        cs[i] = cs[j];
        cs[j] = temp;
    }

利用栈实现:

public class Solution {
    public ArrayList<String> Permutation(String str) {
        TreeSet<String> tree = new TreeSet<>();
       Stack<String[]> stack = new Stack<>();
            ArrayList<String> results = new ArrayList<>();
            stack.push(new String[]{str,""});
            do{
                String[] popStrs = stack.pop();
                String oldStr = popStrs[1];
                String statckStr = popStrs[0];
                for(int i =statckStr.length()-1;i>=0;i--){
                    String[] strs = new String[]{statckStr.substring(0,i)+statckStr.substring(i+1),oldStr+statckStr.substring(i,i+1)};
                    if(strs[0].length()==0){
                        tree.add(strs[1]);
                    }else{
                        stack.push(strs);
                    }
                }
            }while(!stack.isEmpty());
        for(String s : tree)
            results.add(s);
        return results;
    }
}

点赞