216. 组合总和 III
找出所有相加之和为 n
的 k
个数的组合,且满足下列条件:
- 只使用数字1到9
- 每个数字 最多使用一次
返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。
示例 1:
输入: k = 3, n = 7 输出: [[1,2,4]] 解释: 1 + 2 + 4 = 7 没有其他符合的组合了。
示例 2:
输入: k = 3, n = 9 输出: [[1,2,6], [1,3,5], [2,3,4]] 解释: 1 + 2 + 6 = 9 1 + 3 + 5 = 9 2 + 3 + 4 = 9 没有其他符合的组合了。
示例 3:
输入: k = 4, n = 1 输出: [] 解释: 不存在有效的组合。 在[1,9]范围内使用4个不同的数字,我们可以得到的最小和是1+2+3+4 = 10,因为10 > 1,没有有效的组合。
思路:
回溯算法登场,求k个数的和等于n
这个遍历结构可用一棵二叉树来描述,一次选一个元素,然后进入下一层再选一个元素,到叶子节点收获结果,然后回溯,选上一层的另一个元素......
回溯算法模板框架如下:
void backtracking(参数) {
if (终止条件) {
存放结果;
return;
}
for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
处理节点;
backtracking(路径,选择列表); // 递归
回溯,撤销处理结果
}
}
这份模板很重要,后面做回溯法的题目都靠它了!
代码:
class Solution {
public:
vector<vector<int>>result;
vector<int>path;
void backtreacking(int k,int n,int index,int sum)
{
if(sum==n&&path.size()==k)
{
result.push_back(path);
return;
}
for(int i = index;i<=9;i++)
{
sum+=i;
path.push_back(i);
backtreacking(k,n,i+1,sum);
path.pop_back();
sum-=i;
}
}
vector<vector<int>> combinationSum3(int k, int n) {
int sum = 0;
backtreacking(k,n,1,sum);
return result;
}
};
17. 电话号码的字母组合
给定一个仅包含数字 2-9
的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例 1:
输入:digits = "23" 输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
示例 2:
输入:digits = "" 输出:[]
示例 3:
输入:digits = "2" 输出:["a","b","c"]
思路:
用一个string保存每个按键的字符串,
然后用index记录遍历到那层后,用回溯模板解决了
回溯算法的过程可以看成一棵数,一层取一个元素,到叶子节点收获结果,接着向上一层返回,循环往复,直到所有结果都被收获。
代码:
class Solution {
public:
string str[10] ={
"abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"
};
vector<string>result;
string path;
void backtreacking(string digits,int index)
{
if(index==digits.size())
{
result.push_back(path);
return;
}
int ind = digits[index]-'0';
for(int i = 0;i<str[ind-2].size();i++)
{
path.push_back(str[ind-2][i]);
backtreacking(digits,index+1);
path.pop_back();
}
}
vector<string> letterCombinations(string digits) {
if(digits.size()==0) return result;
backtreacking(digits,0);
return result;
}
};
还有很多瑕疵,还需继续坚持!