216.组合总和III
题目链接:216 组合总和III
题目描述:
找出所有相加之和为 n 的 k 个数的组合,且满足下列条件:
只使用数字1到9
每个数字 最多使用一次
返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。
解题思路:
跟昨天的组合差不多,就是多加了个条件而已。
剪枝优化:
- 剪枝一般从两个方面入手,一方面是树的深度,另一方面就是树的宽度。
- 树的深度,就是递归的深度,即遇到不符合条件的立马剪枝,在本题中,即sum已经大于了n,就需要剪枝
- 树的宽度,即循环里面的截止条件,若集合中后序的元素的数量已经不满足了所需要的数量,也立马剪枝。即
i<=9-(k-path.size())+1
。 其中,k-path.size()表示还需要的个数。
class Solution {
public:
vector<vector<int>>result;
vector<int> path;
vector<vector<int>> combinationSum3(int k, int n) {
backtracking(k,n,1,0);
return result;
}
void backtracking(int k,int n,int startIndex,int sum)
{
if(sum>n) return;
if(path.size()==k)
{
if(sum==n)
{
result.push_back(path);
return;
}
}
for(int i=startIndex;i<=9-(k-path.size())+1;i++)
{
path.push_back(i);
sum+=i;
backtracking(k,n,i+1,sum);
sum-=i;
path.pop_back();
}
}
};
17.电话号码的字母组合
题目链接:电话号码的字母组合
题目描述:定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
解题思路:
- 需要借助哈希表,将数字和字母一一对应
- 同样采用回溯的算法。
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
};
public:
vector<string>result;
string s;
vector<string> letterCombinations(string digits) {
if(digits.size()==0) return result;
backtracking(digits,0);
return result;
}
void backtracking(string& digits,int index)
{
if(index==digits.size())
{
result.push_back(s);
return;
}
int num=digits[index]-'0';
string letter=letterMap[num];
for(int i=0;i<letter.size();i++)
{
s.push_back(letter[i]);
backtracking(digits,index+1);
s.pop_back();
}
}
};
注意点:对于backtracking中的参数,是index+1还是i+1,我们不能说记下,而是要具体理解,所谓的index和startindex到底是什么含义。在组合中,所谓的startIndex是只在同一个集合中的起始位置,所以其参数是for循环中的i,而在电话号码中,由于需要从不同的集合中找到对应的第几个集合,因此对应的是不同的集合,应为index,如果是i的话就是指同一个集合了。
(若理解错误,请指出谢谢)