回溯法
回溯法(探索與回溯法)是一種選優搜索法,又稱爲試探法,按選優條件向前搜索,以達到目標。但當探索到某一步時,發現原先選擇並不優或達不到目標,就退回一步重新選擇,這種走不通就退回再走的技術爲回溯法,而滿足回溯條件的某個狀態的點稱爲“回溯點”。由於問題在狀態上又可以視爲一棵多叉樹,所以實際上可以理解爲深度優先搜索(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();
}
}
};