【剑指offer刷题日记 Java版】38. 字符串的排列

458 阅读1分钟

题目

输入一个字符串,打印出该字符串中字符的所有排列。

你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。

示例:

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

解法一 Python版 容易超时

这版其实是我自己经常用的Python版,不稳定,容易超时,但是很简洁

class Solution(object):
    def permutation(self, s):
        """
        :type s: str
        :rtype: List[str]
        """
        result = []
        self.recur(s,"",result)
        return result

    def recur(self,s,cur,result):
        if not s:
            if cur not in result:
                result.append(cur)
                return 
        
        for i in range(len(s)):
            self.recur(s[:i]+s[i+1:],cur+s[i],result)

解法二 Java版 回溯算法

这个解法其实就是用回溯

class Solution {
    List<String> result = new ArrayList<String>();
    char[] candidates;

    public String[] permutation(String s) {
        candidates = s.toCharArray();
        dfs(0);
        return result.toArray(new String[result.size()]);        
    }

    public void dfs(int index){
        // 当到最后一层只剩一个时,把candidates化成string给加入result
        if(index == candidates.length-1){
            result.add(String.valueOf(candidates));
        }
        
        // 记录一下出现过的char,防止重复使用
        HashSet<Character> set = new HashSet<Character>();
        for(int i = index; i < candidates.length;i++){
            if(set.contains(candidates[i])) continue;
            // 把每个index后面的数,都换到index的位置来形成新的组合
            swap(index,i);
            dfs(index+1);
            // 向下回溯后再换回来
            swap(index,i);
        }
    }

    public void swap(int a,int b){
        char temp = candidates[a];
        candidates[a] = candidates[b];
        candidates[b] = temp;
    }
}

时间复杂度 O(n!)

n为字符串 s 的长度;时间复杂度和字符串排列的方案数成线性关系,方案数为 n * (n-1) * (n-2) … ×2×1 ,因此复杂度为 O(n!)

空间复杂度 O(n^2)

递归中辅助 Set 累计存储的字符数量最多为 n + (n-1) + ... + 2 + 1 =(n+1)n/2 ,即占用 O(n^2) 的额外空间 。