组合总和III
题目链接:力扣
这道题和昨天那道组合题的思路是一致的,代码也非常相似。本题k相当于树的深度,9(因为整个集合就是9个数)就是树的宽度。
为了方便理解,我还是 套用了上一题的套路,将路径总和sum的计算放在终止条件中进行判断。当path的数目=k时,比较此时sum和目标值n是否相等。
class Solution {
public:
vector<vector<int>> combinationSum3(int k, int n) {
backtracking(k,n,1);
return result;
}
vector<vector<int>> result;
vector<int> path;
void backtracking(int k,int n, int startIndex)
{
if(path.size() == k)
{
int sum =0;
for(int i=0;i<k;i++)
sum += path[i];
if(sum == n)
result.push_back(path);
return;
}
for(int i= startIndex; i<=9 ;i++)
{
path.push_back(i);
backtracking(k,n,i+1);
path.pop_back();
}
}
};
当然 也可以将sum的计算放在回溯的过程中,这样的话backtracking中就要带4个参数:
void backtracking(int n, int k, int sum, int startIndex)
那么for循环中的内容将改为:sum和path要跟着回溯的过程进行变化!
for (int i = startIndex; i <= 9; i++) {
sum += i; // 处理
path.push_back(i); // 处理
backtracking(n, k, sum, i + 1); // 注意i+1调整startIndex
sum -= i; // 回溯
path.pop_back(); // 回溯
}
电话号码的字母组合
题目链接:力扣
这题感觉很有意思, 一开始做的时候,没有理清楚思路,急于把输入的数字先全部变成字母了,然后后面就遇到了困难。写不下去。
其实呢,输入的字符长度(例如“23”)就代表着遍历的深度,而遍历的长度就是单个数字对应字符串的长度。
这样想就容易很多:
class Solution {
public:
vector<string> res;
string path;
vector<string> letterCombinations(string digits) {
if(digits == "") return res;
backtracking(digits, 0);
return res;
}
void backtracking(const string& digits, int index) //index为记录遍历第几个数字,同时也表示树的深度
{ //递归实现深度 for循环实现宽度
if(path.size() == digits.size())
{
res.push_back(path);
return;
}
int num = digits[index] - '0'; // 将index指向的数字转为int
string letters = corresponding(num); // 取数字对应的字符集
for (int i = 0; i < letters.size(); i++) {
path.push_back(letters[i]); // 处理
backtracking(digits, index + 1); // 递归,注意index+1,一下层要处理下一个数字了
path.pop_back(); // 回溯
}
}
string corresponding(int num)
{
switch(num)
{
case 2: return "abc";
case 3: return "def";
case 4: return "ghi";
case 5: return "jkl";
case 6: return "mno";
case 7: return "pqrs";
case 8: return "tuv";
case 9: return "wxyz";
default: return "";
}
}
};