【Leetcode】46.全排列

103 阅读2分钟

leetcode-46 .png

对于列举所有可能性的这种题目,一般就是要回溯了,一棵树,然后列举所有的可能性,然后根据题目要求,把树上的枝叶裁剪,得到题目所需要的结果

这一题是一个比较典型的回溯题目,按照代码来,也是深度优先遍历DFS

回溯 + 标记

var permute = function (nums) {
    let res = []
    // 标记元素是否使用过
    let used = new Array(nums.length).fill(false)
    // 这里的used也没有必要传入
    var dfs = function (used, one) {
        if (one.length === nums.length) {
            res.push([...one])
            return
        }
        for (let i = 0; i < nums.length; ++i) {
            // 裁剪枝叶,如果已经使用过,那么就到下一元素去
            if (used[i]) continue
            // 标记已经使用过的元素
            used[i] = true
            one.push(nums[i])
            dfs(used, one)
            // 回溯
            used[i] = false
            one.pop()
        }
    }
    dfs(used, [])
    return res
};

✅ 思路说明:

  • 每一层递归代表当前正在选择排列的第 k 位;
  • 使用 used 数组来标记哪些元素已经被使用;
  • 每当 path 长度达到 nums.length,就说明得到了一个完整排列;
  • 回溯的核心在于“尝试 → 回退”,恢复现场以探索下一种可能性。

Swap

一种swap的解法

var permute = function (nums) {
    let res = []
    var dfs = function (start) {
        if (start === nums.length) {
            res.push([...nums])
            return
        }
        // 一般来说,这里的 start 的改变,就是一种剪枝
        for (let i = start; i < nums.length; ++i) {
            [nums[i], nums[start]] = [nums[start], nums[i]]
            dfs(start + 1); // 注意这里的分号
            [nums[start], nums[i]] = [nums[i], nums[start]]
        }
    }
    dfs(0)
    return res
};

✅ 特点:

  • 无需 used 数组,直接对 nums 原地操作;
  • 每轮固定一位,继续对后续元素进行排列;
  • 回溯通过交换复原现场;
  • 空间开销更小,逻辑也更紧凑。

错误代码

下面是错误的代码
可以看到上面的一些注释,对于一些回溯的考点,也是在这里做出一点改变即可
这里我最主要出现的错误就是,对于哪些使用过的元素,是没有感知的,所以就需要一个缓存来做这件事

var permute = function (nums) {
    let res = []
    var dfs = function (start, one) {
        if (one.length === nums.length) {
            res.push([...one])
            return
        }
        // 一般来说,这里的 start 的改变,就是一种剪枝
        for (let i = start; i < nums.length; ++i) {
            one.push(nums[i])
            // 这里 i 的起始点也是有考究的
            dfs(i, one)
            one.pop()
        }
    }
    dfs(0, [])
    return res
};