找出所有相加之和为 n
的 k
个数的组合,且满足下列条件:
- 只使用数字1到9
- 每个数字 最多使用一次
返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。
示例 1:
输入: k = 3, n = 7 输出: [[1,2,4]] 解释: 1 + 2 + 4 = 7 没有其他符合的组合了。
思路:和77题类似,采用回溯递归解决,k相当于深度,n相当于宽度。
解决:首先需要一个二维数组记录所有组合的结果,其次需要一个一维数组记录每次符合条件的组合
确定回溯算法三步
第一步:确定参数;
首先两个参数k和n,其次还要一个记录每次递归开始的记录参数,最后需要一个参数记录当前累加的和;
void backtracking(int n,int k,int start,int sum)
第二步:确定终止条件;
首先符合条件的组合大小不能大于k,等于k的时候终止;其次等于k时候,如果累加和等于n,将组合加入结果二维数组,就可以返回;
if(p.size()==k){
if(sum==n) r.push_back(p);
return;
}
第三步:确定遍历过程。
一个for循环,每次都从新的开始节点遍历,直到n为止,开始节点每次递增;首先和加上当前数字,再从剩下数字递归,如果结果不符合,需要回溯剪去当前数,和也要减去当前数
for(int i=start;i<=n;i++){
sum+=i;
p.push_back(i);
backtracking(n,k,i+1;sum);
p.pop_back(i);
sum-=i;
}
代码:
class Solution {
private:
vector<vector<int>> r;
vector<int> p;
void backtracking(int n,int k,int start,int sum){
if(p.size()==k){
if(sum==n) r.push_back(p);
return;
}
for(int i=start;i<=n;i++){
sum+=i;
p.push_back(i);
backtracking(n,k,i+1,sum);
p.pop_back();
sum-=i;
}
}
public:
vector<vector<int>> combinationSum3(int k, int n) {
p.clear();
r.clear();
backtracking(n,k,1,0);
return r;
}
};
给定一个仅包含数字 2-9
的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例 1:
输入:digits = "23" 输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
思路:其实还是用回溯算法,只要确定深度和宽度就好下手。首先深度跟digits的长度有关,如果是2,树的深度就是2;再看宽度,宽度每次跟digits里的元素值有关,如果是2-9,每次组合的数组长度就为3,如果是1或2,那数组就是空。
解决:首先确定全局变量,一是存储所有结果的数组,二是存储单一结果的数组。其次需要存储每个数字代表的字母,例如n[2]='abc'
确定回溯算法三步。参数和遍历过程比较复杂后考虑
第一步:确定终止条件;
终止条件就是存储单一结果的数组大小等于digits的大小,将结果存到数组中。
第二步:确定遍历过程;
每次都要从新的字母集中选一个进行组合,所以循环从0开始到组合集的大小结束;单一结果的数组存储当前的字母,然后递归下一个字母集,例如当前字母是a,递归字母集就是n[3]='def'。最后如果没有满足添加的组合,回溯,单一结果的数组存储当前的字母。
第三步:确定参数,首先需要知道当前遍历的字母集是哪个,相当于每次递归下标都要加1,然后还需要digits。
代码:
class Solution {
private:
const string letterMap[10] = {
"", // 0
"", // 1
"abc", // 2
"def", // 3
"ghi", // 4
"jkl", // 5
"mno", // 6
"pqrs", // 7
"tuv", // 8
"wxyz", // 9
};
vector<string> r;//所有结果
string s;//单一结果
void backtracking(const string& digits,int i){
if(s.size()==digits.size()){
r.push_back(s);
return;
}
int digit=digits[i]-'0';
string n=letterMap[digit];//根据下表取字母集
for(int j=0;j<n.size();j++){
s.push_back(n[j]);//当前字母进组合
backtracking(digits,i+1);//递归下一个数字对应的字母集
s.pop_back();
}
}
public:
vector<string> letterCombinations(string digits) {
s.clear();
r.clear();
if(digits.size()==0){
return r;
}
backtracking(digits,0);
return r;
}
};