[LeetCode] 46.全排列

46.全排列(回溯)

难度:Medium

题目描述:

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

解题思路:

方法一:
利用一个Used数组记录当前数字是否被使用。
对当前数组Nums进行回溯,注意递归完成之后要清空状态

class Solution {
public:
    vector<vector<int>> permute(vector<int>& nums) {
        vector<vector<int>> res;    // 存放最终所有的排列

        if(nums.size() == 0){
            return res;
        }

        vector<int> temp;                   // 存一次递归中的结果
        vector<int> used(nums.size(), 0);   // 存放哪些数字已经被使用过了
        int usedNum = 0;                    // 记录用过了多少个数字

        generate(res, nums, temp, used, 0);

        return res;
    }

    void generate(vector<vector<int>>& res, vector<int>& nums, vector<int>& temp, vector<int>& used, int usedNum){

        // 递归结束条件:已经找到一个排列
        if(usedNum == nums.size()){
            res.push_back(temp);
            return;
        }

        //依次使用当前数字
        for(int i = 0; i < nums.size(); i++){
            // 判断当前数字是否使用
            if(used[i] == 0){
                used[i] = 1;
                temp.push_back(nums[i]);
                generate(res, nums, temp, used, usedNum + 1);   // 寻找下一个数字
                // 回溯,清空当前的选择
                used[i] = 0;
                temp.pop_back();
            }
        }
        return;
    }
};

方法二:基于交换
维护[0, begin-1]是已经选择过了的数,[begin, n-1]是还没有选择的数。
每次将nums[begin] 和 nums[i]进行交换,保证选择过的数在前面

#include <iostream>
#include <vector>

using namespace std;

class Solution {
private:
    void dfs(vector<int> &nums, int begin, int len, vector<vector<int>> &res) {
        if (begin == len) {
            res.emplace_back(nums);
            return;
        }

        for (int i = begin; i < len; ++i) {
            swap(nums[i], nums[begin]);
            dfs(nums, begin + 1, len, res);
            swap(nums[i], nums[begin]);
        }
    }

public:
    vector<vector<int>> permute(vector<int> &nums) {
        vector<vector<int> > res;
        dfs(nums, 0, (int) nums.size(), res);
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值