216.组合总和|||
思路:这题和77题的组合思路差不多一样,只是多了一步判断加起来的和是否和目标值相等,并且回溯需要把相应的值减去。
代码:
vector<vector<int>> result;
vector<int> path;
void backtracking(int k,int targetSum,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(k,targetSum,sum,i++);
sum -= i;
path.pop_back();
}
}
vector<vector<int>> combinationSum3(int k, int n) {
backtracking(k,n,0,1);
return result;
}
剪纸优化:
优化1:如果当前sum值已经比目标值大了就没必要再继续递归了,因为按递归规则越往下加的数越大,当前sum已经超过了目标值,后面加说明数都超过目标值。
优化2:和77题的优化思路一样,i是控制起点,如果起点到终点之间的数不够k个则不需要再往下遍历。
代码:
vector<vector<int>> result;
vector<int> path;
void backtracking(int k,int targetSum,int sum,int startIndex){
if(sum > targetSum){//优化1
return;
}
if(path.size() == k){
if(sum == targetSum){
result.push_back(path);
return;
}
}
for(int i = startIndex;i <= 9 - (k - path.size()) + 1;i++){//优化2
sum += i;
path.push_back(i);
backtracking(k,targetSum,sum,i+1);
sum -= i;
path.pop_back();
}
}
vector<vector<int>> combinationSum3(int k, int n) {
result.clear();
path.clear();
backtracking(k,n,0,1);
return result;
}
17.电话号码的字母组合
思路:和上面的回溯过程异曲同工,但是startindex不需要了,利用一个index记录当前遍历到第几个数字(第一个则index为0,这样可以方便下标读取字母串),当index==digits.size()则到了叶子节点记录当前的串s(路径)。
代码:
vector<string> result;
string s;//存储当前遍历的字符
void backtracking(const string& digits,int index){//index记录当前遍历到第几个数字
if(index == digits.size()){
result.push_back(s);
return;
}
int digit = digits[index] - '0';//把字符转为相应的数字
string letters = letterMap[digit];//把数字对应的字母串提出
for(int i = 0;i < letters.size();i++){
s.push_back(letters[i]);
backtracking(digits,index+1);//往下一个数字递归
s.pop_back();//回溯
}
}
vector<string> letterCombinations(string digits) {
result.clear();
s.clear();
if(digits.size() == 0) return result;
backtracking(digits,0);
return result;
}