LeetCode - 46. 全排列(回溯)

46. 全排列

给定一个 没有重复 数字的序列,返回其所有可能的全排列。

示例:

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

解题思路: 这题是《剑指offer》书上的题,采取的是不停的交换数据的方法,有点像洗牌,具体的是,每次将start位置的元素与后面的元素进行交换,然后递归地调用start+1的交换。

class Solution {
public:
    void helper(vector<int>& nums, int start, vector<vector<int>>& res) {
         int n = nums.size();
         if (start >= n) {res.push_back(nums); return;}
         for (int i = start; i < n; ++i) {
             swap(nums[start], nums[i]);
             helper(nums, start + 1, res);
             swap(nums[start], nums[i]);
         }
    }
    vector<vector<int>> permute(vector<int>& nums) {
        vector<vector<int>> res;
        helper(nums, 0, res);
        return res;
    }
};

还有一种解法用图的深度优先遍历解题,既然将此题转化成图的遍历,那么现在要解决的是如何构建图,我们可以这样思考,此题是求取全排列,那么全排列的定义是我们不重复的从1…n中取n次点,那么我们可以构建成一个n层的树(图),每层n-1个节点,那么对应到DFS遍历下一个节点,就可以对应到这n-1个节点,至此,情景转化完毕,解析来,我们只需将此题转化为求树的所有路径的题即可解。这是典型的回溯解法,即维护一个路径,遍历的过程中进行伸缩,当遍历完一条路径时,保存结果。

用方法二解题,几乎是暴力解法,时间复杂度会非常高,解全排列的题,依然推荐用交换法解题,解法二的回溯思想可以借鉴。

class Solution {
public:
    void helper(vector<int>& nums, vector<bool>& visited, vector<int> out, vector<vector<int>>& res) {
        if (out.size() == nums.size()) {res.push_back(out); return;}
        for (int i = 0; i < nums.size(); ++i) {
            if (visited[i]) continue;
            visited[i] = true;
            out.push_back(nums[i]);
            helper(nums, visited, out, res);
            visited[i] = false;
            out.pop_back();
        }
    }
    vector<vector<int>> permute(vector<int>& nums) {
        int n = nums.size();
        vector<bool> visited(n, false);
        vector<vector<int>> res;
        helper(nums, visited, {}, res);
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值