116、【回溯算法】leetcode ——17. 电话号码的字母组合:回溯法:哈希映射+字符串数组映射(C++/Python版本)

题目描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
原题链接:17. 电话号码的字母组合

解题思路

  1. 构建电话数字和字母映射关系
  2. 回溯操作,选择一个数字的中对应的一个字母。

哈希表映射

用Hash表构建字符型数字和字母的映射关系。

class Solution {
public:
    // 记录结果集
    vector<string> res;     
    // 构建电话数字和字母的映射关系
    void buildNumString(map<char, string> &table) {
        char startIndex = 'a';
        for(char i = '2'; i <= '9'; i++) {
            string s = "";
            char ch = startIndex;
            while(ch <= startIndex + 2 && ch <= 'z') {
                s += ch++;
            }         
            if(i == '7') {
                ch = 't';
                s += 's';
            }
            startIndex = ch;
            table[i] = s;
        }
        table['9'] += "z"; 
    }
    // digits:输入数字,s:已记录对应字母,startIndex:起始下标,table:映射表
    void backtracking(string digits, string s, int startIndex, map<char, string> table) {        
        if(s.size() == digits.size()) {
            res.push_back(s);
        }        
        // 外层遍历输入的数字,内层遍历每个数字对应的字母,每次更新起始下标
        for(int i = startIndex; i < digits.size(); i++) {
            for(int j = 0; j < table[digits[i]].size(); j++) {
                backtracking(digits, s + table[digits[i]][j], i + 1, table);
            }            
        }
    }
    vector<string> letterCombinations(string digits) {
        if(digits.size() == 0)          return {};
        map<char, string> table;
        buildNumString(table);
        backtracking(digits, "", 0, table);

        return res;
    }
};

Python

class Solution:
    def __init__(self):
        self.digit_dict = {
            '2': 'abc',
            '3': 'def',
            '4': 'ghi',
            '5': 'jkl',
            '6': 'mno',
            '7': 'pqrs',
            '8': 'tuv',
            '9': 'wxyz'
        }
        self.path = ''
        self.res = []


    def backtracking(self, digits, start_index):
        if len(self.path) == len(digits):
            self.res.append(self.path)
            return
        
        for i in range(start_index, len(digits)):
            chars = self.digit_dict[digits[i]]
            for j in range(len(chars)):
                self.path += chars[j]
                self.backtracking(digits, i + 1)
                self.path = self.path[:-1]


    def letterCombinations(self, digits: str) -> List[str]:
        if len(digits) == 0:
            return []

        self.backtracking(digits, 0)
        return self.res


代码优化:字符串数组映射

将Hash表改用string数组,降低空间复杂度、提高了存储效率。

class Solution {
public:
    // 记录结果集
    vector<string> res;     
    // 构建电话数字和字母的映射关系
    void buildNumString(string table[]) {
        table[0] = "";
        table[1] = "";
        char startIndex = 'a';
        for(int i = 2; i <= 9; i++) {
            string s = "";
            char ch = startIndex;
            while(ch <= startIndex + 2 && ch <= 'z') {
                s += ch++;
            }
            if(i == 7) {
                ch = 't';
                s += 's';
            }
            startIndex = ch;
            table[i] = s;
        }
        table[9] += "z";             
    }
    // digits:输入数字,s:已记录对应字母,startIndex:遍历的数字下标,table:映射表
    void backtracking(string digits, string s, int startIndex, string table[]) {        
        if(s.size() == digits.size()) {
            res.push_back(s);
            return ;
        }        
        // 获取遍历的数字和对应的字母串
        int digit = digits[startIndex] - '0';
        string letters = table[digit];
        // 遍历该数字对应的字母串
        for(int i = 0; i < letters.size(); i++) {
            backtracking(digits, s + letters[i], startIndex + 1, table);
        }
    }
    vector<string> letterCombinations(string digits) {
        if(digits.size() == 0)          return {};
        string table[10];
        buildNumString(table);
        backtracking(digits, "", 0, table);

        return res;
    }

};

参考文章:17.电话号码的字母组合

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

辰阳星宇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值