回溯法
回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。由于问题在状态上又可以视为一棵多叉树,所以实际上可以理解为深度优先搜索(DFS)。
例题1
https://leetcode-cn.com/problems/generate-parentheses/
题目描述
Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
For example, given n = 3, a solution set is:
[ "((()))", "(()())", "(())()", "()(())", "()()()" ]
解析
每个位置只有两种选择,可视作二叉树。根据条件可以适当剪枝:(1)每种括号个数最多为n;(2)从开头到任意一个位置,右括号个数不能多于左括号个数。
class Solution {
private:
vector<string> ans;
string s;
public:
vector<string> generateParenthesis(int n) {
dfs(0,0,n);
return ans;
}
void dfs(int left,int right,int &n){ //左右括号的个数
if(left==right&&s.size()==n*2) {
ans.push_back(s);
s.pop_back();
return;
}
if(left<n) {
s+="(";
dfs(left+1,right,n);
}
if(left>right){
s+=")";
dfs(left,right+1,n);
}
if(!s.empty()) s.pop_back();
}
};
例题2
https://leetcode-cn.com/problems/combination-sum/
题目描述
Given a set of candidate numbers (candidates
) (without duplicates) and a target number (target
), find all unique combinations in candidates
where the candidate numbers sums to target
.
The same repeated number may be chosen from candidates
unlimited number of times.
Note:
- All numbers (including
target
) will be positive integers. - The solution set must not contain duplicate combinations.
Example 1:
Input: candidates =[2,3,6,7],
target =7
A solution set is: [ [7], [2,2,3] ]
Example 2:
Input: candidates = [2,3,5],
A solution set is:
[
[2,2,2,2],
[2,3,3],
[3,5]
]
解析
问题的关键在于如何去重。可以通过让每次只能往上一次的后面查找,不到到前面查找,这样就可以避免重复,每次将上一个元素的位置作为递归参数传入到下一层作为下一层的起始位置。
class Solution {
private:
vector<int> temp;
vector<vector<int>> ans;
public:
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
dfs(target,0,candidates);
return ans;
}
void dfs(int target,int index,vector<int>& candidates){
for(int i=index;i<candidates.size();i++){
if(candidates[i]>target) continue;
temp.push_back(candidates[i]);
if(candidates[i]==target){
ans.push_back(temp);
}
else dfs(target-candidates[i],i,candidates);
temp.pop_back();
}
}
};