1.全排列
1.1 题目
1.2 思路
1.3 代码
class Solution {
public:
vector<vector<int>> ret;//最终结果变量
vector<int> path;//单次搜索
bool check[7];//判断路径上的元素是否已经选择过
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;
}
//循环遍历nums中的每个元素
for(int i = 0; i < nums.size(); i++)
{
if(check[i] == false)//这个数还没加入到path
{
path.push_back(nums[i]);//把这个数加入到path
check[i] = true;//把check坐上true标记,表示已加入到path
dfs(nums);//进行深度优先遍历
//dfs完了之后,就相当于进入决策树的下一个分支了
//回溯 -> 恢复现场
path.pop_back();
check[i] = false;
}
}
}
};
2.子集
2.1 题目
2.2 思路
2.3 代码
方法一
//方法一 灵神代码
//这段代码实现了一个经典的算法问题:给定一个整数数组 nums,返回其所有可能的子集(幂集)。
//幂集是指一个集合的所有子集组成的集合,包括空集和集合本身。
//代码使用了深度优先搜索(DFS)的方法来生成所有子集。
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> ret;//存储返回结果:最终生成的所有子集
vector<int> path;//在递归过程中记录当前正在构建的子集
int n = nums.size();//nums数组的大小
//n:递归过程中用于判断是否已经处理完数组中的所有元素
//定义了一个递归函数 dfs,用于深度优先搜索生成所有子集。
//auto 表示函数的返回类型会自动推导,这里返回类型为 void。
//this auto&& dfs 是一个 C++17 的特性,表示 dfs 是一个可调用对象(可以是函数、lambda 表达式等),并且支持递归调用自身。
//int i 是递归函数的参数,表示当前处理到数组 nums 的第 i 个元素。
auto dfs = [&](this auto&& dfs, int i) -> void {
//递归的终止条件
if (i == n) { // 子集构造完毕
ret.emplace_back(path);
return;
}
// 选nums[i]
path.push_back(nums[i]);
dfs(i + 1);
path.pop_back(); // 回溯到上一层,需要pop掉push的元素,恢复现场
// 不选nums[i]
dfs(i + 1);
};
dfs(0);
return ret;
}
};
//方法一 代码二 更好理解
class Solution {
public:
vector<vector<int>> ret;
vector<int> path;
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;
}
// 1.选nums[pos]
path.push_back(nums[pos]);
dfs(nums, pos + 1);
path.pop_back();//回溯到上一层时,恢复现场,pop;
//2.不选nums[pos]
dfs(nums, pos + 1);
}
};
方法二
class Solution {
public:
vector<vector<int>> ret;
vector<int> path;
vector<vector<int>> subsets(vector<int>& nums) {
dfs(nums, 0);
return ret;
}
void dfs(vector<int>& nums, int pos)
{
ret.push_back(path);//每次进入递归都要先push,每次进入递归都是一个结果
for(int i = pos; i < nums.size(); i++)
{
path.push_back(nums[i]);//先加入当前元素
dfs(nums, i + 1);//继续往下递归
path.pop_back();//恢复现场
}
}
};