思路出处:
http://www.acwing.com
我是一看就会,一写就废。先看代码:
class Solution {
public:
vector<vector<int>> res;
vector<int> path;
vector<vector<int>> combinationSum3(int k, int n) {
dfs(1,k,n);
return res;
}
void dfs(int start,int k,int n)
{
if(!n)
{
if(!k) res.push_back(path);
else return;
}
else if(k)
{
for(int i = start;i <= 9;i++)
{
if(n >= i)
{
path.push_back(i);
dfs(i + 1,k - 1,n - i);
path.pop_back();
}
}
}
}
};
这道题目和组合数是很像的,组合数的方法就是到达一定条件就加入到结果中,这里仍然是,只不过又多了一个条件就是选择的数字中加和等于n,所以判断每次结束的条件除了看看答案包含的个数是否是正确的之外,还有就是n是否为0。这里计算数字和的方法和Letcode的第一题或者是三数和、四数和的方法类似,都不是去找数加,而是去减。这里的思想是每次只要n比i大就把i加入结果中,暂且叫做初筛的过程,就是每次的差是n,我每次找的结果要么是比n小的,要么是等于n的,但绝对不会找比n大的,然后到了if(!n)这里就是二次筛选,这次就是只筛选三数和相加为n的。只有n为的时候才可以执行这个if的条件。
先看代码:
class Solution {
public:
vector<string> res;
vector<string> num = {" "," ","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
vector<string> letterCombinations(string digits) {
if(digits.empty()) return res;
dfs(digits,0,"");
return res;
}
void dfs(string digits,int n,string path)
{
if(n == digits.size()) res.push_back(path);
else
{
for(auto& c:num[digits[n] - '0'])
dfs(digits,n + 1,path + c);
}
}
};
这道题目感觉比较难,因为是字母的组合,但是这也加深了我对于回溯的理解,这里的第一个问题就是如何将字符串串转换成数字,第一个方法是可以开一个map,第二个方法就是减去’0’,这样就可以将字符转换成字符串。然后就是组合的方法了。这里应该有人会有疑问,说为什么path不用恢复现场,因为这里的path是形参,每次调用这个函数的时候都会初始化,所以也省去了恢复现场的步骤。