力扣第46题 全排列 c++ 回溯 秒杀题 思路+注释

题目

46. 全排列

中等

相关标签

数组   回溯

给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

示例 1:

输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

示例 2:

输入:nums = [0,1]
输出:[[0,1],[1,0]]

示例 3:

输入:nums = [1]
输出:[[1]]

提示:

  • 1 <= nums.length <= 6
  • -10 <= nums[i] <= 10
  • nums 中的所有整数 互不相同

思路和解题方法

  1. ans 是保存所有排列结果的二维数组。
  2. path 是当前正在构造的排列。
  3. backtracking 是递归回溯函数,用于生成排列。
    1. 首先判断当前排列的长度是否等于给定数组的长度,如果是,说明已经生成了一个完整的排列,将其加入到 ans 中,并返回。
    2. 然后遍历给定数组中的元素,如果该元素已经被使用过,跳过不处理。
    3. 否则,将该元素标记为已使用 true,将其加入到当前排列 path 后面,然后递归调用 backtracking 继续构造剩余部分的排列。
    4. 在递归完成后,需要进行回溯操作,即将当前元素从 path 中移除,将其标记为未使用 false,以便生成其他排列。
  4. permute 函数是主函数,用于初始化变量并调用 backtracking 进行排列的生成。
  5. 最后返回 ans 即为所有可能的排列结果。

复杂度

        时间复杂度:

                O(N! * N)

  • 时间复杂度:O(N! * N),其中 N 是数组的长度。算法通过回溯的方式生成所有可能的排列,而每个排列的长度是 N。因此总共有 N! 个排列,每个排列需要 O(N) 的时间复杂度来生成。

        空间复杂度

                O(N)

  • 空间复杂度:O(N),其中 N 是数组的长度。算法使用了额外的一个长度为 N 的数组 path 来保存当前已选取的元素,以及一个长度为 N 的数组 used 来记录数字是否已经被使用过。此外,还有一个二维数组 ans 用于保存所有的排列结果。因此总共需要 O(N) 的空间复杂度。

c++ 代码

class Solution {
public:
    vector> ans; // 存储所有排列结果的二维数组
    vector path; // 当前正在构造的排列

    /**
     * 回溯函数,用于生成排列
     * @param nums 给定数组
     * @param used 标记数组,记录每个元素是否已经被使用
     */
    void backtracking(vector &nums, vector &used) {
        if (path.size() == nums.size()) { // 当前排列的长度等于给定数组的长度,已经生成了一个完整的排列
            ans.push_back(path); // 将当前排列加入到结果集中
            return;
        }

        for (int i = 0; i < nums.size(); i++) { // 遍历给定数组中的元素
            if (used[i]) continue; // 如果该元素已经被使用过,跳过不处理

            used[i] = true; // 将该元素标记为已使用
            path.push_back(nums[i]); // 将该元素加入到当前排列中
            backtracking(nums, used); // 递归调用,继续构造剩余部分的排列
            path.pop_back(); // 回溯操作,将当前元素移出当前排列
            used[i] = false; // 将该元素标记为未使用,以便生成其他排列
        }
    }

    /**
     * 生成给定数组的全排列
     * @param nums 给定数组
     * @return 所有可能的排列结果
     */
    vector> permute(vector& nums) {
        ans.clear(); // 清空结果数组
        path.clear(); // 清空当前排列

        vector used(nums.size(), false); // 初始化标记数组,所有元素都未被使用

        backtracking(nums, used); // 调用回溯函数进行排列生成

        return ans; // 返回所有可能的排列结果
    }
};

觉得有用的话可以点点赞,支持一下。

如果愿意的话关注一下。会对你有更多的帮助。

每天都会不定时更新哦  >人<  。

你可能感兴趣的:(leetcode,回溯,数据结构,算法,leetcode,c++,回溯)