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

 

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

 

示例:

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

 

限制:

1 <= s 的长度 <= 8

Related Topics
  • 字符串
  • 回溯
  • \n
  • 👍 391
  • 👎 0
  • 题解

    看起来有点面熟,很直白的深度搜索回溯算法。

    根据所给字符串s,挨个位置遍历,在新得出的字符串的每一位上穷举,并记录已举过的字符串,在穷举的时候,如果已经存在于已使用过的位置的集合的记录中,则跳过。

    而最终要求“里面不能有重复元素”,所以最终的结果集用set集合保存,直接进行去重。

    class Solution {
    
    
        private HashSet<String> list;
    
        private Integer length;
    
        public String[] permutation(String s) {
            list = new HashSet<>();
            length = s.length();
            HashSet<Integer> visited = new HashSet<>();
            dfs(s.toCharArray(),visited,0,new char[s.length()]);
            return list.toArray(new String[0]);
        }
    
    
        private void dfs(char[] charArr,HashSet<Integer> visited,int index,char[] newCharArr){
            if (index==length){
                list.add(new String(newCharArr));
                return;
            }
            for (int i = 0; i < charArr.length; i++) {
                if (visited.contains(i)){
                    continue;
                }
                visited.add(i);
                newCharArr[index] = charArr[i];
                dfs(charArr,visited,index+1,newCharArr);
                visited.remove(i);
            }
        }
    }

    结果

    解答成功:
    执行耗时:69 ms,击败了10.93% 的Java用户
    内存消耗:44.2 MB,击败了21.26% 的Java用户

    而在结果集没有使用set集合的时候,跑这样一个用例出了问题。

    测试用例:"aab"
    测试结果:["aab","aba","aab","aba","baa","baa"]
    期望结果:["aba","aab","baa"]

    所以,取第一个a还是第二个a是没有区别的,这边之前记录的是HashSet<Integer> visited字符串的索引位置,所以在此之外,可以再借助一个字符串集合进行剪枝操作Set<Character> sameChar。剪枝之后的结果集也可以不用set集合了,直接更简单的List集合替代。

    另外还有一点小小的改动,一开始写的visited是Set集合,而记录内容是某个索引位置是否访问过,都知道索引的特征是从0-N连续的,这边可以再简化成一个boolean[] visited数组。

    
    //leetcode submit region begin(Prohibit modification and deletion)
    class Solution {
    
    
        private List<String> list;
    
        private Integer length;
    
        public String[] permutation(String s) {
            list = new ArrayList<>();
            length = s.length();
            boolean[] visited = new boolean[s.length()];
            dfs(s.toCharArray(),visited,0,new char[s.length()]);
            String[] res = new String[list.size()];
            int i = 0;
            for (String s1 : list) {
                res[i] = s1;
                i++;
            }
            return res;
        }
    
    
        private void dfs(char[] charArr,boolean[] visited,int index,char[] newCharArr){
            if (index==length){
                list.add(new String(newCharArr));
                return;
            }
            Set<Character> sameChar = new HashSet<>();
            for (int i = 0; i < charArr.length; i++) {
                if (visited[i]){
                    continue;
                }
                if (sameChar.contains(charArr[i])){
                    continue;
                }
                sameChar.add(charArr[i]);
                visited[i] = true;
                newCharArr[index] = charArr[i];
                dfs(charArr,visited,index+1,newCharArr);
                visited[i] = false;
            }
        }
    }
    //leetcode submit region end(Prohibit modification and deletion)
    
    
    解答成功:
    执行耗时:14 ms,击败了64.61% 的Java用户
    内存消耗:42.7 MB,击败了73.19% 的Java用户