算法-回溯
1.给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
示例:
输入: nums = [1,2,3]
输出:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/subsets
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
1 class Solution { 2 void generate(vector<int> sub,vector<int>& nums,int i,vector<vector<int>>& result){ 3 if(i==nums.size()) return; 4 sub.push_back(nums[i]); 5 result.push_back(sub); 6 generate(sub,nums,i+1,result); 7 vector<int> next=sub; 8 next.pop_back();//回溯 9 generate(next,nums,i+1,result); 10 } 11 public: 12 vector<vector<int>> subsets(vector<int>& nums) { 13 vector<vector<int>> result; 14 vector<int> sub; 15 result.push_back(sub); 16 generate(sub,nums,0,result); 17 return result; 18 19 } 20 };
位运算方法
class Solution{ public: vector<vector<int>> subsets(vector<int>& nums) { vector<vector<int>> result; int n=nums.size(); int len=1<<n;//结果总长度 for(int i=0;i<len;++i){ vector<int> sub; for(int j=0;j<n;++j){ if(i & (1<<j)){//与1,2,4分别进行“与”运算,得到是否将数字放入数组 sub.push_back(nums[j]); } } result.push_back(sub); } return result; } };
2.给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
示例:
输入: [1,2,2]
输出:
[
[2],
[1],
[1,2,2],
[2,2],
[1,2],
[]
]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/subsets-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution { void generate(vector<int> sub,int i,vector<int>& nums,vector<vector<int>>& result,set<vector<int>>& res_set){ if(i>=nums.size()) return; sub.push_back(nums[i]); if(res_set.find(sub)==res_set.end()){ res_set.insert(sub); result.push_back(sub); } generate(sub,i+1,nums,result,res_set); sub.pop_back(); generate(sub,i+1,nums,result,res_set); } public: vector<vector<int>> subsetsWithDup(vector<int>& nums) { vector<vector<int>> result; set<vector<int>> res_set;//去重 sort(nums.begin(),nums.end());//排序 vector<int> sub; result.push_back(sub); res_set.insert(sub); generate(sub,0,nums,result,res_set); return result; } };
3.给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用一次。
说明:
所有数字(包括目标数)都是正整数。
解集不能包含重复的组合。
示例 1:
输入: candidates = [10,1,2,7,6,1,5], target = 8,
所求解集为:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]
示例 2:
输入: candidates = [2,5,2,1,2], target = 5,
所求解集为:
[
[1,2,2],
[5]
]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/combination-sum-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution { public: int n; vector<vector<int>> result; vector<int> sub; vector<vector<int>> combinationSum2(vector<int>& candidates, int target) { n=candidates.size(); sort(candidates.begin(),candidates.end()); generate(candidates,target,0); return result; } void generate(vector<int>& candidates,int target,int index){ if(target<0){ return; }else if(target==0){ result.push_back(sub); return; }else{ for(int i=index;i<n && candidates[i]<=target;++i){ if(i>index && candidates[i-1]==candidates[i]) continue; //去重 sub.push_back(candidates[i]); generate(candidates,target-candidates[i],i+1); sub.pop_back(); } } } };
4.给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。
例如,给出 n = 3,生成结果为:
[
"((()))",
"(()())",
"(())()",
"()(())",
"()()()"
]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/generate-parentheses
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution { vector<string> result; int max; public: vector<string> generateParenthesis(int n) { int l=0,r=0; max=n; generate(l,r,""); return result; } void generate(int l,int r,string s){ if(r==max){ result.push_back(s); return; } if(l>=r){ if(l<max) generate(l+1,r,s+'('); if(l!=r){ if(r<max) generate(l,r+1,s+')'); } } } };
5.n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
示例:
输入: 4
输出: [
[".Q..", // 解法 1
"...Q",
"Q...",
"..Q."],
["..Q.", // 解法 2
"Q...",
"...Q",
".Q.."]
]
解释: 4 皇后问题存在两个不同的解法。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/n-queens
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution { vector<string> solve; vector<vector<string>> result; int n; public: vector<vector<string>> solveNQueens(int n) { vector<vector<int>> canPutQueen; this->n=n; for(int i=0;i<n;++i){ vector<int> v; canPutQueen.push_back(v); string s; solve.push_back(s); for(int j=0;j<n;++j){ solve[i].push_back('.'); canPutQueen[i].push_back(0); } } putQueen(0,0,canPutQueen); return result; } void putQueen(int i,int j,vector<vector<int>>& canPutQueen){ if(i==n) { result.push_back(solve); return; } if (j == n) return;//此处要先判定j==n,否则下面vector会访问越界 if(canPutQueen[i][j]>0){ if(j==n-1) return; putQueen(i,j+1,canPutQueen); }else{ solve[i][j]='Q'; setCanPutQueen(i,j,canPutQueen,1); putQueen(i+1,0,canPutQueen); solve[i][j]='.'; setCanPutQueen(i,j,canPutQueen,-1); putQueen(i,j+1,canPutQueen); } } //设置可放标志数组,可回撤 void setCanPutQueen(int i,int j,vector<vector<int>>& canPutQueen,int m){ for(int k=0;k<n;k++){ canPutQueen[i][k]+=m; canPutQueen[k][j]+=m; if(i+j-k>=0&&i+j-k<n){ canPutQueen[k][i+j-k]+=m; } if(k+j-i>=0&&k+j-i<n){ canPutQueen[k][k+j-i]+=m; } } } };