一、216.组合总和III
题目链接/文章讲解/视频讲解: https://programmercarl.com/0216.%E7%BB%84%E5%90%88%E6%80%BB%E5%92%8CIII.html状态:已解决
1.思路
做过77题(上篇博客)后,这道题也就不难了,无非是多加了一个条件:组合之和等于n,只需要将这个加到终止条件那里即可。但这道题也有简化的地方,就是明确了每个样例的整个集合已经是固定的[1,...,9]。做过77就明白此题的做题套路了。
直接套模板:
(1)返回值为空,参数需要有:每层递归for循环的开始值m(组合无序,若每层递归for循环都是1~9,那么会出现{1,3}和{3,1}这种相同的组合方式)、前面递归所选值的累加和sum、n、k。
void backtracking(int m,int k,int n,int sum)
(2)终止条件:vec.size() == k(vec是存放一条路径的变量),sum==n。
if(vec.size() == k){if(sum==n)result.push_back(vec);return ;//一定要return
}
(3)单层递归逻辑:for循环m~9,i的值放入vec中,sum加上i,开始子递归,然后再将i弹出。
for(int i=m;i<=9;i++){vec.push_back(i);backtracking(i+1,k,n,sum+i);vec.pop_back();
}
2.完整代码
class Solution {
public:vector<int> vec;vector<vector<int>> result;void backtracking(int m,int k,int n,int sum){if(vec.size() == k){if(sum==n)result.push_back(vec);return ;}for(int i=m;i<=9;i++){vec.push_back(i);backtracking(i+1,k,n,sum+i);vec.pop_back();}}vector<vector<int>> combinationSum3(int k, int n) {vec.clear();result.clear();backtracking(1,k,n,0);return result;}
};
另外,还可以减枝:当sum>n时,也终止。(for循环终止条件也可以为 i<9-(k-vec.size())+1 ,跟vec.size()==k终止差不多,故未添加。)
class Solution {
public:vector<int> vec;vector<vector<int>> result;void backtracking(int m,int k,int n,int sum){if(sum > n) return;if(vec.size() == k){if(sum==n)result.push_back(vec);return ;}for(int i=m;i<=9;i++){vec.push_back(i);backtracking(i+1,k,n,sum+i);vec.pop_back();}}vector<vector<int>> combinationSum3(int k, int n) {vec.clear();result.clear();backtracking(1,k,n,0);return result;}
};
二、LeetCode77.组合
题目链接/文章讲解/视频讲解: https://programmercarl.com/0017.%E7%94%B5%E8%AF%9D%E5%8F%B7%E7%A0%81%E7%9A%84%E5%AD%97%E6%AF%8D%E7%BB%84%E5%90%88.html状态:已解决
1.思路
首先,这里有一段对应关系,每个数字对应几个字符。因此,我们第一步需要先存一个对应的字典。(这里可以用字符串数组存,也可以用vector<string>存,当然也可以用map做映射)
map<string,string> dic;
Solution() {dic["2"] = "abc";dic["3"] = "def";dic["4"] = "ghi";dic["5"] = "jkl";dic["6"] = "mno";dic["7"] = "pqrs";dic["8"] = "tuv";dic["9"] = "wxyz";
}
做完这步后面回溯三部曲就跟前面的差不多了。
(1)返回值为空,参数需要有:目前遍历到digits的位置k、目前选择路径path、digits。
void backtracking(string digits, int k, string path)
(2)终止条件digits.size() == k,sum==n。
if(digits.size() == k){result.push_back(path);return ;
}
(3)单层递归逻辑:根据k得出当前位置的数字,根据字典得到该数字对应的字符串,然后用for循环选择的字符加入现有路径中。
string s = dic[digits.substr(k, 1)];
for(int i=0; i<s.size(); i++){backtracking(digits, k+1, path + s[i]);
}
2.完整代码
class Solution {
public:map<string,string> dic;vector<string> result;Solution() {dic["2"] = "abc";dic["3"] = "def";dic["4"] = "ghi";dic["5"] = "jkl";dic["6"] = "mno";dic["7"] = "pqrs";dic["8"] = "tuv";dic["9"] = "wxyz";}void backtracking(string digits, int k, string path){if(digits.size() == k){result.push_back(path);return ;}string s = dic[digits.substr(k, 1)];for(int i=0; i<s.size(); i++){backtracking(digits, k+1, path + s[i]);}}vector<string> letterCombinations(string digits) {result.clear();if(digits.size() == 0) {return result;}backtracking(digits, 0, "");return result;}
};