剑指offer_38_字符串的排序【Javascript】

49 阅读1分钟

题目链接

leetcode.cn/problems/zi…

题目

输入一个字符串,打印出该字符串中字符的所有排列。例如,输入字符串abc,则打印出由字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和cba。

示例:

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

限制:

  • 1 <= s 的长度 <= 8

题解

回溯

复杂度分析

  • 时间复杂度:O(n×n!),其中 n 为给定字符串的长度。这些字符的全部排列有 O(n!) 个,每个排列平均需要 O(n) 的时间来生成。
  • 空间复杂度:O(n)。我们需要 O(n) 的栈空间进行回溯,注意返回值不计入空间复杂度。
/**
 * @param {string} s
 * @return {string[]}
 */
/**
 * @param {string} s
 * @return {string[]}
 */

var permutation = function(s) {
    const res = [], vis = [];
    const n = s.length;
    const strArray = Array.from(s).sort(); // 排序方便下面字符去重
    const perm = [];
    
    const backtrack = (strArray, i) => {
        if (i === n) {
            res.push(perm.toString()); // 固定完所有字符,放入数组中
            return;
        }
        for (let j = 0; j < n; j++) {
            if (vis[j] || (j > 0 && !vis[j - 1] && strArray[j - 1] === strArray[j])) {
                // 去重(已经走过的 或者 遇到两个相同字母的情况)
                continue;
            }
            vis[j] = true; // 标记已经用过
            perm.push(strArray[j]);
            backtrack(strArray, i + 1); // 填下一个位置
            perm.pop();
            vis[j] = false;
        }
    }

    backtrack(strArray, 0);

    const size = res.length;
    const recArr = new Array(size).fill(0);
    for (let i = 0; i < size; i++) {
        recArr[i] = res[i].split(',').join('');
    }
    return recArr;
};