Skip to content
本页目录

38-字符串的排列

题目描述

https://leetcode.cn/problems/zi-fu-chuan-de-pai-lie-lcof

输入一个字符串,打印出该字符串中字符的所有排列。 你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。

示例:

输入:s = "abc"
输出:["abc","acb","bac","bca","cab","cba"]

限制:

1 <= s 的长度 <= 8

思路:回溯法

全排列, 回溯法 使用 dfs 遍历所有元素索引,将循环结果去重加入 list

代码1,会超时

csharp
public class Solution {
	
	List<int> arrIndex;
	List<string> result;
    
	private void dfs(char[] arr){
		if(arrIndex.Count == arr.Length){
			//循环结束
			string str = "";
			for(int i=0;i<arrIndex.Count;i++){
				str+=arr[arrIndex[i]];
			}
            //取出重复元素
            if(!result.Contains(str)){
                result.Add(str);
            }
		}

		for(int i=0; i<arr.Length; i++){
			if(!arrIndex.Contains(i)){
				arrIndex.Add(i);
				dfs(arr);
				arrIndex.Remove(i);
			}
		}
	}

    public string[] Permutation(string s) {
    	arrIndex = new List<int>();
    	result = new List<string>();
    	dfs(s.ToCharArray());
    	return result.ToArray();
    }
}

代码2,使用visited 数组优化比较,直接拼凑字符串:还是超时

测试用例:"dkjphedy"

csharp
public class Solution {
	List<string> result;
    private int[] visited;
	private void dfs(string s, string str){
		if(s.Length == str.Length){
            //取出重复元素
            if(!result.Contains(str)){
                result.Add(str);
            }
		}

		for(int i=0; i<s.Length; i++){
			if(visited[i] == 0){
				str+=s[i];
                visited[i] = 1;
				dfs(s,str);
                str=str.Substring(0,str.Length-1);
                visited[i] = 0;
			}
		}
	}

    public string[] Permutation(string s) {
        visited = new int[s.Length];
    	result = new List<string>();
    	dfs(s,"");
    	return result.ToArray();
    }
}

代码3,最终版:使用 visited 数组,然后排序原字符串数组去掉重复的数组,加速执行

csharp
public class Solution {
	List<string> result;
    private int[] visited;
	private void dfs(char[] s, StringBuilder str){
		if(s.Length == str.Length){
            //取出元素:因为回溯的时候,去掉了重复的内容,所以此处可以直接添加
            result.Add(str.ToString());
		}
		for(int i=0; i<s.Length; i++){
			if(visited[i] == 1 || ( i > 0 && s[i] == s[i-1] && visited[i-1] == 1) ){
                continue;
			}
            str.Append(s[i]);
            visited[i] = 1;
            dfs(s,str);
            str.Length--;
            visited[i] = 0;
		}
	}

    public string[] Permutation(string s) {
        //排序去重,减少时间执行
        char[] arr = s.ToArray();
        Array.Sort(arr);
        visited = new int[s.Length];
    	result = new List<string>();
        StringBuilder str = new StringBuilder();
    	dfs(arr,str);
    	return result.ToArray();
    }
}

复习:20220508

csharp
public class Solution {

    private List<string> result;
    private List<char> list;
    private bool[] visited;

    private void dfs(char[] s, int index){
        if(index == s.Length){
            result.Add(new string(list.ToArray()));
            return;
        }
        for(int i=0; i<s.Length; i++){
            //取出重复
            if(visited[i] || i > 0 && visited[i-1] && s[i] == s[i-1]){
                continue;
            }
            list.Add(s[i]);
            visited[i] = true;
            dfs(s,index+1);
            visited[i] = false;
            list.RemoveAt(list.Count-1);
        }
    }

    public string[] Permutation(string s) {
        list = new List<char>();
        result = new List<string>();

        visited = new bool[s.Length];
        char[] arr = s.ToArray();
        Array.Sort(arr);
        dfs(arr,0);
        return result.ToArray();
    }
}

复习去重 : 20220611

去重逻辑 strs[i] == strs[i-1] ,比如 当 aab 的时候, 加入了第一个a,dfs的时候,第二个a就不会加入。 所以第一次递归完 是 ab 结束, 当第二个从第二个 a dfs的时候,就会 第一层【第二个】a, 第二层【第一个】a,然后b,组成符合条件输出。 总结下来就是,从后面往前推算的相同字符才算,否则都不算这样只有一个结果。

csharp
public class Solution {

    private List<string> list = new List<string>();

    private void dfs(char[] strs, int index, StringBuilder sb, bool[] used){
        if(index == strs.Length){ //输出
            list.Add(sb.ToString());
            return;
        }
        for(int i=0; i<strs.Length; i++){
            if(!used[i]){
                if(i>0 && used[i-1] && strs[i] == strs[i-1]){
                    continue;
                }

                sb.Append(strs[i].ToString());
                used[i] = true;
                dfs(strs,index+1,sb, used);
                sb.Length--;
                used[i] = false;
            }
        }
    }

    public string[] Permutation(string s) {
        StringBuilder sb = new StringBuilder();
        bool[] used = new bool[s.Length];
        char[] strs = s.ToArray();
        Array.Sort(strs);
        dfs(strs,0,sb,used);
        return list.ToArray();
    }
} 

Released under the MIT License.