216.组合总和III 题目链接
思路
首先想到的是暴力解法,但明显对于k值稍微大些的情况,时间复杂度极高。
故采用回溯法,用递归代替for循环。
解题方法
树的深度代表k值,树的宽度代表集合。
递归函数参数:目标和,k值,当前和,遍历的起始位置
终止条件:叶子结点或者当前和已经大于目标和。
单层搜索过程:横向遍历for循环,这里可以剪枝,缩小i的范围。
Code
class Solution {
private:
vector<vector<int>>result;
vector<int>path;
void backtracking(int targetSum,int k,int sum,int startIndex)
{
//if(sum>targetSum)return;
if(path.size()==k)
{
if(sum==targetSum)result.push_back(path);
return;
}
for(int i=startIndex;i<=9-(k-path.size())+1;i++)
{
sum+=i;
path.push_back(i);
backtracking(targetSum,k,sum,i+1);
sum-=i;
path.pop_back();
}
}
public:
vector<vector<int>> combinationSum3(int k, int n) {
result.clear();
path.clear();
backtracking(n,k,0,1);
return result;
}
};
17.电话号码的字母组合题目链接
思路
数字和字母映射,使用map或定义一个二位数组
解题方法
取数字的个数做为树的深度,每个数字包含的字母个数作为树的宽度。用一个变量来记录取得数字个数。
回溯函数参数:字符串型的数字,用来记录的变量
终止条件:inde等于数字的个数
单层遍历逻辑:用for循环来处理这个字符集
用二位数组result收集结果
Code
class Solution {
private:
const string letterMap[10]={
"",
"",
"abc",
"def",
"ghi",
"jkl",
"mno",
"pqrs",
"tuv",
"wxyz",
};
public:
vector<string>result;
string s;
void backtrackikng(const string&digits,int index){
if(index==digits.size()){
result.push_back(s);
return;
}
int digit=digits[index]-'0';
string letters=letterMap[digit];
for(int i=0;i<letters.size();i++)
{
s.push_back(letters[i]);
backtrackikng(digits,index+1);
s.pop_back();
}
}
vector<string> letterCombinations(string digits) {
s.clear();
result.clear();
if(digits.size()==0)
{
return result;
}
backtrackikng(digits,0);
return result;
}
};