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;
}
};