代码随想录算法训练营第二十五天| LeetCode216.组合总和III、17.电话号码的字母组合

一、216.组合总和III

状态:已解决

1.思路 

        做过77题(上篇博客)后,这道题也就不难了,无非是多加了一个条件:组合之和等于n,只需要将这个加到终止条件那里即可。但这道题也有简化的地方,就是明确了每个样例的整个集合已经是固定的[1,...,9]。做过77就明白此题的做题套路了。

        直接套模板:

(1)返回值为空,参数需要有:每层递归for循环的开始值m(组合无序,若每层递归for循环都是1~9,那么会出现{1,3}和{3,1}这种相同的组合方式)、前面递归所选值的累加和sum、n、k。

void backtracking(int m,int k,int n,int sum)

(2)终止条件:vec.size() == k(vec是存放一条路径的变量),sum==n。

if(vec.size() == k){
    if(sum==n)
        result.push_back(vec);
    return ;//一定要return
}

(3)单层递归逻辑:for循环m~9,i的值放入vec中,sum加上i,开始子递归,然后再将i弹出。

for(int i=m;i<=9;i++){
    vec.push_back(i);
    backtracking(i+1,k,n,sum+i);
    vec.pop_back();
}

2.完整代码

class Solution {
public:
    vector<int> vec;
    vector<vector<int>> result;
    void backtracking(int m,int k,int n,int sum){
        if(vec.size() == k){
            if(sum==n)
                result.push_back(vec);
            return ;
        }
        for(int i=m;i<=9;i++){
            vec.push_back(i);
            backtracking(i+1,k,n,sum+i);
            vec.pop_back();
        }
    }
    vector<vector<int>> combinationSum3(int k, int n) {
        vec.clear();
        result.clear();
        backtracking(1,k,n,0);
        return result;
    }
};

另外,还可以减枝:当sum>n时,也终止。(for循环终止条件也可以为 i<9-(k-vec.size())+1 ,跟vec.size()==k终止差不多,故未添加。)

class Solution {
public:
    vector<int> vec;
    vector<vector<int>> result;
    void backtracking(int m,int k,int n,int sum){
        if(sum > n) return;
        if(vec.size() == k){
            if(sum==n)
                result.push_back(vec);
            return ;
        }
        for(int i=m;i<=9;i++){
            vec.push_back(i);
            backtracking(i+1,k,n,sum+i);
            vec.pop_back();
        }
    }
    vector<vector<int>> combinationSum3(int k, int n) {
        vec.clear();
        result.clear();
        backtracking(1,k,n,0);
        return result;
    }
};

二、LeetCode17.电话号码的字母组合

状态:已解决

1.思路

        首先,这里有一段对应关系,每个数字对应几个字符。因此,我们第一步需要先存一个对应的字典。(这里可以用字符串数组存,也可以用vector<string>存,当然也可以用map做映射)

map<string,string> dic;
Solution() {
    dic["2"] = "abc";
    dic["3"] = "def";
    dic["4"] = "ghi";
    dic["5"] = "jkl";
    dic["6"] = "mno";
    dic["7"] = "pqrs";
    dic["8"] = "tuv";
    dic["9"] = "wxyz";
}

         做完这步后面回溯三部曲就跟前面的差不多了。

 (1)返回值为空,参数需要有:目前遍历到digits的位置k、目前选择路径path、digits。

void backtracking(string digits, int k, string path)

(2)终止条件digits.size() == k,sum==n。

if(digits.size() == k){
    result.push_back(path);
    return ;
}

(3)单层递归逻辑:根据k得出当前位置的数字,根据字典得到该数字对应的字符串,然后用for循环选择的字符加入现有路径中。

string s = dic[digits.substr(k, 1)];
for(int i=0; i<s.size(); i++){
    backtracking(digits, k+1, path + s[i]);
}

2.完整代码

class Solution {
public:
    map<string,string> dic;
    vector<string> result;
    
    Solution() {
        dic["2"] = "abc";
        dic["3"] = "def";
        dic["4"] = "ghi";
        dic["5"] = "jkl";
        dic["6"] = "mno";
        dic["7"] = "pqrs";
        dic["8"] = "tuv";
        dic["9"] = "wxyz";
    }
    
    void backtracking(string digits, int k, string path){
        if(digits.size() == k){
            result.push_back(path);
            return ;
        }
        string s = dic[digits.substr(k, 1)];
        for(int i=0; i<s.size(); i++){
            backtracking(digits, k+1, path + s[i]);
        }
    }
    
    vector<string> letterCombinations(string digits) {
        result.clear();
        if(digits.size() == 0) {
            return result;
        }
        backtracking(digits, 0, "");
        return result;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值