目录
Leetcode 216.组合总和III
题目链接:Leetcode 216.组合总和III
题目描述:找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字。
思路:首先,这是一道组合问题,即:N个数里面按一定规则找出k个数的集合,因此本题可以使用回溯算法。我对回溯的理解就是:用普通的嵌套for循环实现不了(本道题是无法确定嵌套循环的层数),而借助递归的一种暴力模拟方法。而回溯算法的精髓在于:无论怎么调用下一层递归函数,我们要保证本层递归函数的内容不发生变化,如果必须改变,则需要在下一层递归函数结束后恢复原状。以本题为例,我们在递归过程中需要将符合条件的数字放到一个组合中(用数组储存),那么在调用下一层递归之后需要把加入这个数字从组合中(也就是数组中)去掉,以保证本层递归函数内容不变。
代码如下:
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtracking(int target, int k, int sum, int start) {
if (sum > target)//如果当前数字总和已经比目标值大了,就没必要再搜索了
return;
if (sum == target) {//相等则加入结果集中
if (path.size() == k)
result.push_back(path);
return;
}
for (int i = start; i <= 9 - (k - path.size()) + 1; i++) {
sum += i;
path.push_back(i);
backtracking(target, k, sum, i + 1);
//恢复原状(回溯)
sum -= i;
path.pop_back();
}
}
vector<vector<int>> combinationSum3(int k, int n) {
backtracking(n, k, 0, 1);
return result;
}
};
Leetcode 17.电话号码的字母组合
题目描述:给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
思路:本题也是一道组合问题,即:N个数里面按一定规则找出k个数的集合,因此可以使用回溯算法,接下来要注意的就是数字和字符串的映射问题,我们可以使用map或者二维数组来解决。
代码如下:
class Solution {
public:
const string letterMap[10] = {
"", // 0
"", // 1
"abc", // 2
"def", // 3
"ghi", // 4
"jkl", // 5
"mno", // 6
"pqrs", // 7
"tuv", // 8
"wxyz", // 9
};
vector<string> result;
string s;
void backtracking(const string& digits,int index) { // index用来记录当前遍历到哪个数字了
if (index == digits.size()) {
result.push_back(s);
return;
}
int digit = digits[index] - '0'; //把访问到的数字字符对应的数字取出来
string letter = letterMap[digit];
for (int i = 0; i < letter.size(); i++) {
s.push_back(letter[i]);
backtracking(digits, index + 1);
s.pop_back(); //回溯(恢复原状)
}
}
vector<string> letterCombinations(string digits) {
if (digits.size() == 0)
return result;
backtracking(digits, 0);
return result;
}
};
总结:今天的回溯也不算难,不过想一次写对也不太容易。
最后,如果文章有错误,请在评论区或私信指出,让我们共同进步!