子集
78. 子集
法一:思路对每个元素进行选与不选的 选择,这样正好到最后一层 就是2的size()次方个,叶子就是节点,通过pos来控制深度
法二:通过for循环实现,且下一个栈帧的i是上一个栈帧当前元素的下一个位置 ,能起到vis的作用刚开始写的时候把这个->dfs(nums, i + 1); 写成了dfs(nums, pos + 1);
解释为什么dfs(nums, pos + 1);是错的且当样例为[1,2,3]时有16个结果
其实就是逻辑上不对,每一个for循环进到下一个栈帧的区间都是一样的,这就是问题所在;
总结:在for里i=pos上,有一点点语法的混淆,加上脑子不清醒,逻辑不清晰,梳理好了在写,不然还得重新检查
法一:
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;}path.push_back(nums[pos]);dfs(nums, pos + 1);path.pop_back();dfs(nums,pos + 1);}
};
法二:
class Solution {
public:vector<int> path;vector<vector<int>> ret;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();}}
};
全排列
46. 全排列
通过pos来控制栈帧深度,pos+1来增加深度,pos也是用来取值的
在代码上表现逻辑:当需要dfs往下走的时候,需要对已经当前元素改bool值,来保证到下一层不被使用;当dfs回来之后自然的要把当前元素弹出path(其实每个栈的深度,就是这个元素在path里的位置)我们只需要弹出它,让他去后面的其他位置,同时需要解锁bool值
题外话:保持其他代码不变,删掉弹出语句,最大长度是多少?
答:15个,第一个栈帧可以发送3个值,同时需要三个栈帧(注意:在此时深度仍然是2),这三个栈帧每个可以向下个栈帧发送2个值,会有6个栈帧;这6个栈帧每个可以发送一个值,那就是2+3*2+6=15,一共会创建16个栈帧(因为到进不去for那个栈帧才结束),最大深度为4
class Solution {
public:vector<vector<int>> ret;vector<int> path;vector<bool> vis;//bool[6];vector<vector<int>> permute(vector<int>& nums) {vis.resize(nums.size());dfs(nums, 0);return ret;}void dfs(vector<int>& nums, int pos){if(pos == nums.size()){ret.push_back(path);return;}for(int i = 0; i < nums.size(); i++){if(vis[i] == true) continue;path.push_back(nums[i]);vis[i] = true;dfs(nums, pos + 1);path.pop_back();vis[i] = false;}}
};
找出所有子集的异或总和再求和
1863. 找出所有子集的异或总和再求和
class Solution {
public:int ret = 0;int subsetXORSum(vector<int>& nums) {dfs(nums, 0, 0);return ret;}void dfs(vector<int>& nums, int pos, int sum){ret += sum;for(int i = pos; i < nums.size(); i++){sum = sum ^ nums[i];dfs(nums, i + 1, sum);sum ^= nums[i];}}
};
全排列 II
47. 全排列 II
1. 去重想到的就是set,set里放vector<int>
2. 剪枝
class Solution {
public:set<vector<int>> set;vector<bool> vis;vector<int> path;vector<vector<int>> permuteUnique(vector<int>& nums) {vis.resize(nums.size());dfs(nums, 0);vector<vector<int>> ret(set.begin(), set.end());return ret;}void dfs(vector<int>& nums, int pos){if(path.size() == nums.size()){set.insert(path);}for(int i = 0; i < nums.size(); i++){if(vis[i]) continue;path.push_back(nums[i]);vis[i] = true;dfs(nums, pos + 1);vis[i] = false;path.pop_back();}}
};
class Solution {
public:vector<bool> vis;vector<int> path;vector<vector<int>> ret;vector<vector<int>> permuteUnique(vector<int>& nums) {vis.resize(nums.size());sort(nums.begin(), nums.end());dfs(nums, 0);return ret;}void dfs(vector<int>& nums, int pos){if(pos == nums.size()){ret.push_back(path);return;}for(int i = 0; i < nums.size(); i++){if(vis[i] == true || i != 0 && nums[i] == nums[i - 1] && vis[i - 1] == false) continue;path.push_back(nums[i]);vis[i] = true;dfs(nums, pos + 1);path.pop_back();vis[i] = false;}}
};
电话号码的字母组合
17. 电话号码的字母组合
代码问题:arr[digits[pos] - '0'];忘记是字符了
逻辑问题:digiis可能是空串,空串进入dfs就会被压入 "" 空字符串
class Solution {
public:vector<string> arr{ "","","abc","def" ,"ghi","jkl","mno","pqrs","tuv","wxyz"};vector<string> ret;string path;vector<string> letterCombinations(string digits) {if(digits.size() == 0) return ret;dfs(digits, 0);return ret;}void dfs(string digits, int pos){if (pos == digits.size()){ret.push_back(path);return;}string tmp = arr[digits[pos] - '0'];for (auto e : tmp){path.push_back(e);dfs(digits, pos + 1);path.pop_back();}}
};
组合
77. 组合
class Solution {
public:vector<int> path;vector<bool> vis;vector<vector<int>> ret;int _k;vector<vector<int>> combine(int n, int k) {_k = k;vector<int> arr(n);for (int i = 0; i < n; i++)arr[i] = i + 1;dfs(arr, 0);return ret;}void dfs(vector<int>& arr, int pos){if (path.size() == _k){ret.push_back(path);return;}for (int i = pos; i < arr.size(); i++){path.push_back(arr[i]);dfs(arr, i + 1);path.pop_back();}}
};
class Solution {
public:vector<int> path;vector<vector<int>> ret;int _k, _n;vector<vector<int>> combine(int n, int k) {_k = k;_n = n;dfs(0);return ret;}void dfs(int pos){if (path.size() == _k){ret.push_back(path);return;}for (int i = pos; i < _n; i++){path.push_back(i + 1);dfs(i + 1);path.pop_back();}}
};
目标和
494. 目标和
发现局部sum不需要sum += nums[pos];这样的加回去的操作,因为每一个栈帧里的sum都是不一样的,而全局sum会一直改变,一个栈帧里的操作不能影响同层栈帧
全局sum
class Solution {
public:int sum = 0, ret = 0,_target;int findTargetSumWays(vector<int>& nums, int target) {_target = target;dfs(nums, 0);return ret;}void dfs(vector<int>& nums, int pos){if (pos == nums.size()){if (_target == sum)ret++;return;}sum += nums[pos];dfs(nums, pos + 1);sum -= nums[pos];sum -= nums[pos];dfs(nums, pos + 1);sum += nums[pos];}
};
局部sum
class Solution {
public:int ret = 0,_target;int findTargetSumWays(vector<int>& nums, int target) {_target = target;dfs(nums, 0, 0);return ret;}void dfs(vector<int>& nums, int pos, int sum){if (pos == nums.size()){if (_target == sum)ret++;return;}sum += nums[pos];dfs(nums, pos + 1, sum);sum -= nums[pos];sum -= nums[pos];dfs(nums, pos + 1, sum);}
};
组合总和
39. 组合总和
参开代码
class Solution {
public:vector<int> path;int _target;vector<vector<int>> ret;vector<vector<int>> combinationSum(vector<int>& candidates, int target) {_target = target;dfs(candidates, 0, 0);return ret;}void dfs(vector<int>& nums, int pos, int sum){if(sum == _target){ret.push_back(path);return;}if(sum > _target || pos == nums.size()) return;for(int i = 0; i * nums[pos] + sum <= _target; i++){if(i) path.push_back(nums[pos]);dfs(nums, pos + 1, i * nums[pos] + sum);// while(i--)// path.pop_back(); //不对必须是整个for结束,不然i走不下去了}for(int i = 1; i * nums[pos] + sum <= _target; i++) path.pop_back();}
};
超时:
class Solution {
public://vector<vector<int>> ret;int _target, sum = 0;vector<int> path;set<vector<int>> set;vector<vector<int>> combinationSum(vector<int>& candidates, int target) {vector<int> nums;for (auto e : candidates){int n = target / e;for (int i = 0; i < n; i++)nums.push_back(e);}_target = target;dfs(nums, 0);vector<vector<int>> ret(set.begin(), set.end());return ret;}void dfs(vector<int>& nums, int pos){if(sum == _target)set.insert(path);if (pos == nums.size()) return;for (int i = pos; i < nums.size(); i++){path.push_back(nums[i]);sum += nums[i];dfs(nums, i + 1);sum -= nums[i];path.pop_back();}}
};
括号生成
22. 括号生成
条件约束递归
class Solution {
public:string path;vector<string> ret;int _n, left = 0, right = 0;vector<string> generateParenthesis(int n) {_n = n;dfs();return ret;}void dfs(){if(right == _n) {ret.push_back(path);return;}if (left < _n){path.push_back('(');left++, dfs();path.pop_back(); left--;}if (right < left){path.push_back(')');right++, dfs();path.pop_back(); right--;}}};
判断是不是平衡二叉树
判断是不是平衡二叉树_牛客题霸_牛客网
dfs的返回值 :-1为false 非0为高度差,这个想法很6★★★★
left和right是不用+1的,因为这个1是root这个位置
class Solution {
public:bool IsBalanced_Solution(TreeNode* pRoot) {return dfs(pRoot) != -1;}int dfs(TreeNode* root){if (root == nullptr) return 0;int left = dfs(root->left);if (left == -1) return -1;int right = dfs(root->right);if (right == -1) return -1;return abs(left - right) <= 1 ? max(left, right) + 1: -1;}
};