216.组合总和III
思路:和上一道组合的题相比,仅仅多了一个和的限制。
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtracking(int targetsum,int k,int sum,int startindex){
if(path.size()==k){
if(sum==targetsum){
result.push_back(path);
return;
}
}
for(int i=startindex;i<=9;i++){
sum+=i;
path.push_back(i);
backtracking(targetsum,k,sum,i+1);
path.pop_back();
sum-=i;
}
return;
}
vector<vector<int>> combinationSum3(int k, int n) {
result.clear();
path.clear();
backtracking(n,k,0,1);
return result;
}
};
剪枝操作:
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtracking(int targetsum,int k,int sum,int startindex){
if(sum>targetsum) return;//第一处剪枝
if(path.size()==k){
if(sum==targetsum){
result.push_back(path);
return;
}
}
for(int i=startindex;i<=9-(k-path.size())+1;i++){//第二处剪枝
sum+=i;
path.push_back(i);
backtracking(targetsum,k,sum,i+1);
path.pop_back();
sum-=i;
}
return;
}
vector<vector<int>> combinationSum3(int k, int n) {
result.clear();
path.clear();
backtracking(n,k,0,1);
return result;
}
};
错因:第一步剪枝写成了≥,如果恰好收集到了k个元素,且sum=targetsum的话,如果终止条件有等于的话就返回了,那下面就不会收集到结果。
17.电话号码的字母组合
思路:一般来说回溯算法的递归函数都是没有返回值,也就是void。
本题中数字到字符串还需要一个映射,我么可以用map做映射,也可以用一个二维数组做映射。用二维数组会方便一点,我们得到数字后(也就是下标),直接把它放到二维数组中就可以得到对应的字符串了。
注意从本题的示例中可以看出,我们最终要返回一个数组类型的结果。
class Solution {
public:
string lettermap[10]={
"",
"",
"abc",
"def",
"ghi",
"jkl",
"mno",
"pqrs",
"tuv",
"wxyz",
};
string s;
vector<string> result;
void backtracking(const string& digits,int index){
if(index==digits.size()){
result.push_back(s);
return;
}
int digit=digits[index]-'0';
string letter=lettermap[digit];
for(int i=0;i<letter.size();i++){
s.push_back(letter[i]);
backtracking(digits,index+1);
s.pop_back();
}
return;
}
vector<string> letterCombinations(string digits) {
s.clear();
result.clear();
if(digits.size()==0) return result;
backtracking(digits,0);
return result;
}
};
注意加const是为了不被修改,加引用是为了防止拷贝,占用内存空间。