例一:全排列
题目:给一个不含重复数的数组,返回其所有可能的全排列
示例:
给出一个数组nums[1,2,3],返回其所有的全排列为[1,2,3],[1,3,2],[2,3,1],[2,1,3],[3,1,2],[3,2,1].
方法:
1:画出决策树(一定要先画出决策树来辅助思考)
每一层都是在三选一,然后不可以选中与前几次一样的数
2:设计代码
全局变量
int[][] ret;(表示最终要返回的所有排列)
int[] path;(表示每一条排列,将其记录在path中,再由path放进ret中)
bool[] check;(标记位置,看是否被使用过·,从而决定是否要使用该条路径)
dfs函数(仅需关心某一个节点在做什么)
细节问题
回溯:要将最后一个元素排除,并且将其位置重置
剪枝:利用check[]数组,实现剪枝
递归出口:遇到叶子节点,直接添加结果
class Solution {
vector<vector<int>> ret;
vector<int> path;
bool check[7];
public:
vector<vector<int>> permute(vector<int>& nums) {
dfs(nums);
return ret;
}
void dfs(vector<int>& nums)
{
//出口,返回之后再进行回溯
if(nums.size()==path.size())
{
ret.push_back(path);
return;
}
//进行枚举
for(int i = 0;i<nums.size();i++)
{
if(check[i] == false)
{
path.push_back(nums[i]);
check[i] = true;
dfs(nums);
//回溯
path.pop_back();
check[i] = false;
}
}
}
};
例二:子集
题目:给出一个整数数组,元素各不相同,返回其所有的子集
示例:
给出一个数组nums[1,2,3],其所有的子集为:(1)(2)(3)(1 2)(1 3)(2 3)(1 2 3)
方法一:叶子节点为所求的子集
1:画出决策树
每一层都要分两种,选不选当前的数
2:设计代码
全局变量
int [] path;(记录路径)
int[][] ret;(存放结果)
dfs函数
dfs(nums,i)
选的话:path+=nums[i],dfs(nums,i)
不选:dfs(nums,i+1)
递归出口
i==nums.size()
class Solution {
vector<int> path;
vector<vector<int>> ret;
public:
vector<vector<int>> subsets(vector<int>& nums) {
dfs(nums, 0);//后面数字要表示现在选择到哪儿了
return ret;
}
void dfs(vector<int>& nums, int pos)
{
if (pos == nums.size())//递归出口
{
ret.push_back(path);
return;
}
//选
path.push_back(nums[pos]);
dfs(nums, pos + 1);
path.pop_back();
//不选
dfs(nums, pos + 1);
}
};
方法二:
1:画决策树
每一层都是所求的子集
2:设计代码
全局变量
int [] path;(记录路径)
int[][] ret;(存放结果)
dfs函数
dfs(nums,pos)(pos表示位置,当前位置该从何处进行枚举)
class Solution {
vector<int> path;
vector<vector<int>> ret;
public:
vector<vector<int>> subsets(vector<int>& nums) {
dfs(nums, 0);//后面数字要表示现在选择到哪儿了
return ret;
}
void dfs(vector<int>& nums, int pos)
{
ret.push_back(path);
for (int i = pos; i < nums.size(); i++)
{
path.push_back(nums[i]);
dfs(nums, i + 1);
path.pop_back();//恢复现场
}
}
};