LeetCode 17. 电话号码的字母组合:

17. 电话号码的字母组合

  

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

示例 1:

输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]

示例 2:

输入:digits = ""
输出:[]

示例 3:

输入:digits = "2"
输出:["a","b","c"]

提示:

  • 0 <= digits.length <= 4
  • digits[i] 是范围 ['2', '9'] 的一个数字。

思路:

参考LeetCode题解,利用 回溯,这题类似于LeetCode 46. 全排列,都可以运用 "前进 + 回退" 的回溯法实现

(另外,也可参考此题解:LeetCode题解,包含回溯模板)

时间复杂度 / 空间复杂度:(参考LeetCode官方题解): 


 Go版本:

// dfs 递归
// 1、构造map映射表
// 2、先获取当前数字,再从map中取出该数字对应的字母映射
// 3、遍历该数字对应的字母映射,不断将其追加到子结果集中
// 4、如果一个组合的长度达到了len(digits),则将子结果集追加到结果集中(递归终止条件)
func letterCombinations(digits string) []string {
    res := make([]string, 0)

    m := map[byte]string{
        '2': "abc",
        '3': "def",
        '4': "ghi",
        '5': "jkl",
        '6': "mno",
        '7': "pqrs",
        '8': "tuv",
        '9': "wxyz",
    }

    var dfs func(subRes string, k int)
    dfs = func(subRes string, k int) {
        // 如果一个组合的长度达到了len(digits),则将子结果集追加到结果集中
        if k == len(digits) {
            res = append(res, subRes)
            return
        }

        // 先获取当前数字,再从map中取出该数字对应的字母映射
        digit := digits[k]
        str := m[digit]
        for _, ch := range str {
            dfs(subRes + string(ch), k+1)

            // subRes = subRes + string(ch)
            // dfs(subRes, k+1)
            // subRes = subRes[:len(subRes)-1] // 回溯,避免当前子结果影响下一层递归结果
        }
    }

    // 主逻辑
    if digits == "" {
        return []string{}
    }

    dfs("", 0)
    return res
}

 C++版本:

// 回溯: 前进 + 回退
vector<string> letterCombinations(string digits) {
    if (digits == "")
        return {};
        
    vector<string> combinations;
    string combination;
    DFS(digits, 0, combination, combinations);
    return combinations;
}

void DFS(string digits, int level, string combination, vector<string>& combinations) // combinations加引用:每次复用该空间:否则每次回退时,会清理掉该空间,结果为空(若不加引用则要定义为函数外部的全局变量)
{
    if (level == digits.size()) // level表示按到第几个数字键了,而不是数字对应的字母(按键"23"都按完了. digits.size() = 2)
    {
        combinations.push_back(combination);
        return; 
    }

    for (int i = 0; i < m[digits[level]].size(); i++)       // m[digits[level]].size():表示数字键对应字母串的长度,比如:2对应"abc"长度为3
    {
        combination.push_back(m[digits[level]][i]);         // 前进:临时结果压入一个字母
        DFS(digits, level + 1, combination, combinations);  // level + 1:按下一个数字键,比如:2 -> 3
        combination.pop_back();                             // 回退:状态还原,例如临时结果从 "ab" -> "a",下一次循环尝试"ac" 
    }
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值