剑指 Offer 38. 字符串的排列

题目

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

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

示例:

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

限制:

  • 1 <= s 的长度 <= 8

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof

解题思路

全排列问题,使用回溯法解决
不能有重复元素,两种解决方案:去重或者剪枝
本题使用回溯+剪枝

代码

class Solution {
    // 字符串转字符数组
    char[] cArr;
    // 用来保存字符串全排列
    List<String> list;
    public String[] permutation(String s) {
        // 初始化
        cArr = s.toCharArray();
        list = new ArrayList<>();
        // 回溯 + 剪枝
        dfs(0);
        return list.toArray(new String[list.size()]);
    }

    private void dfs(int index) {
        // 递归结束条件,当前递归到字符数组最后一个元素
        if (index == cArr.length - 1) {
            // 添加字符串,并返回
            list.add(String.valueOf(cArr));
            return;
        }

        // 使用HashSet进行去重,剪枝
        HashSet<Character> set = new HashSet<>();
        // 其实每进行一次循环,就是固定下来index下标的元素
        for (int i = index; i < cArr.length; i++) {
            // 剪枝操作
            // 判断当前元素是否重复,重复的话直接跳出当前循环,继续下一轮循环
            if (!set.add(cArr[i])) {
                continue;
            }
            // 做出决策,交换元素
            swap(i, index);
            // 回溯
            dfs(index + 1);
            // 撤销决策,交换回来
            swap(i, index);
        }
    }

    private void swap(int i, int j) {
        // 交换元素
        char c = cArr[i];
        cArr[i] = cArr[j];
        cArr[j] = c;
    }
}

复杂度

  • 时间复杂度:O(n!),n的阶乘
  • 空间复杂度:O(n2),全排列递归深度为n,去重hashset存储元素最多为n + (n - 1) + (n - 2) + … + 2 + 1 = (n + 1) * n / 2,额外空间约为n2

你可能感兴趣的:(leetcode,leetcode,剑指offer,回溯)