【字符串&回溯】——剑指 Offer38字符串的排列

186 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

题目

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

思路

1.这是一个典型的回溯算法解题,对chars.length 个字符进行逐个选择,

2.从chars数组中选择字符组成一个长度为chars.length的字符串,先从0位置开始选择,此时index=0,可以从中任意选择一个字符,当已经选择了这个字符就把这个字符与index位置进行交换,表示到达index位置的字符是已经排列好的,index++;

3.当排列到chars.length-1个字符时,把这个StringBuilder.toString()加入到set集合中

4.需要注意的是每次dfs后需要就原来的位置进行还原,这样做的目的是为了不干扰其他组合情况

注意:每次向dfs传入StringBuilder的时候需要new一个新的对象,不然的话就会干扰其他情况。

代码

class Solution {
    char[] chars;
    Set<String> set;

    public String[] permutation(String s) {
        chars = s.toCharArray();  
        set = new HashSet<>(); //set用于过滤重复的组合
        dfs(new StringBuilder(), 0);
        String[] res = new String[set.size()];  //用于返回结果
        int index = 0; //辅助res的下标
        // System.out.println(set.size());
        for (String str : set) {  //遍历set集合
            res[index++] = str;
        }
        return res;
    }

    public void dfs(StringBuilder sb, int index) { //表示到达的位置
        if (index == chars.length - 1) {
            set.add(new StringBuilder(sb).append(chars[index]).toString());
            return;
        }
        for (int i = index; i < chars.length; i++) { 
            swap(i, index); //index位置是要更改的位置
            dfs(new StringBuilder(sb).append(chars[index]), index + 1);
            swap(i, index);  //还原
        }

    }

    public void swap(int i, int j) {
        char temp = chars[i];
        chars[i] = chars[j];
        chars[j] = temp;
    }
}