代码随想录【Day 25】 | 216.组合总和III、17.电话号码的字母组合

216.组合总和III

题目链接:216.组合总和III

卡尔文解

视频讲解

解题思路及注意事项:

本题就是在[1,2,3,4,5,6,7,8,9]这个集合中找到和为n的k个数的组合。

相对于77. 组合 (opens new window),无非就是多了一个限制,本题是要找到和为n的k个数的组合,而整个集合已经是固定的了[1,…,9]。

想到这一点了,做过77. 组合 (opens new window)之后,本题是简单一些了。

本题k相当于树的深度,9(因为整个集合就是9个数)就是树的宽度。

例如 k = 2,n = 4的话,就是在集合[1,2,3,4,5,6,7,8,9]中求 k(个数) = 2, n(和) = 4的组合。

选取过程如图:

在这里插入图片描述
图中,可以看出,只有最后取到集合(1,3)和为4 符合条件。

代码实现:

class Solution {

private:
    vector<int> path;
    vector<vector<int>> result;
    int cur_sum = 0;

    void back_tracking( int k, int target_sum, int start_idx ){

        if( path.size() > k ){
            return;
        }

        if(( target_sum == cur_sum ) && path.size() == k ){
            result.push_back( path );
            return;
        }

        for ( int i = start_idx; i <= 9; i++ ){
            
            path.push_back( i );
            cur_sum += i;
            back_tracking( k, target_sum, i + 1 );
            cur_sum -= i;
            path.pop_back();

        }
    }

public:
    vector<vector<int>> combinationSum3(int k, int n) {

        back_tracking( k, n, 1 );
        return result;
    }
};

17.电话号码的字母组合

题目链接:17.电话号码的字母组合

卡尔文解

视频讲解

解题思路及注意事项:

从示例上来说,输入"23",最直接的想法就是两层for循环遍历了吧,正好把组合的情况都输出了。

如果输入"233"呢,那么就三层for循环,如果"2333"呢,就四层for循环…

大家应该感觉出和77.组合 (opens new window)遇到的一样的问题,就是这for循环的层数如何写出来,此时又是回溯法登场的时候了。

理解本题后,要解决如下三个问题:

数字和字母如何映射
两个字母就两个for循环,三个字符我就三个for循环,以此类推,然后发现代码根本写不出来
输入1 * #按键等等异常情况
#数字和字母如何映射
可以使用map或者定义一个二维数组,例如:string letterMap[10],来做映射,我这里定义一个二维数组,代码如下:

在这里插入图片描述

回溯法来解决n个for循环的问题
对于回溯法还不了解的同学看这篇:关于回溯算法,你该了解这些!(opens new window)

例如:输入:“23”,抽象为树形结构,如图所示:

在这里插入图片描述
图中可以看出遍历的深度,就是输入"23"的长度,而叶子节点就是我们要收集的结果,输出[“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”]。

代码实现:

class Solution {

string path;
vector<string> result;

string key_string_map[ 10 ] = {
    "",     "",     "abc",
    "def",  "ghi",  "jkl",
    "mno",  "pqrs", "tuv",
    "wxyz"
};

void back_tracking( string digits, int idx ){

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

    int i = digits[ idx ] - '0';
    string letters = key_string_map[ i ];

    for( int i = 0; i < letters.size(); i++ ){
        path.push_back( letters[ i ]);
        back_tracking( digits, idx + 1 );
        path.pop_back();
    }
}

public:
    vector<string> letterCombinations(string digits) {

        if( digits.empty() ) return {};

        back_tracking( digits, 0 );
        return result;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值