力扣17题-电话号码的字母组合

题目

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。

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

示例:

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

说明:

尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。

链接:https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number

解答

因为给出的号码字符串长度不定, 用常规的循环嵌套难以实现. 本题可以使用递归解决, 本文依旧使用循环法.(如输入数字为 “233”)

  1. 第一步先处理号码只有一位的情况的答案
    [“a”,“b”,“c”]

  2. 当进行第 i 步时, 会有前 i 步 已经找好的组合, 用这些已经找好的组合再与新的号码组
    ([“a”,“b”,“c”]与[“d”,“e”,“f”]组合结果为[“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”].)

  3. 如果还有还有第三位以及更多位的数字, 反复执行第二步直到数字用完.
    (此时找[“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”] 与 [“d”,“e”,“f”] 的组合)

代码

/*
*给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。
*给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
*
*示例:
*
*输入:"23"
*输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
*/
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;
ostream& operator<<(ostream& os, vector<string>& v)
{
	os << '[';
	for (auto iter = v.begin(); iter < v.end() - 1; iter++)
	{
		os << '"' << *iter << "\" ," << endl;
	}
	os << '"' << *(v.end() - 1) << '"'<< ']';
	return os;
}
class Solution {
public:
	vector<string> letterCombinations(string digits) {
		// 电话键盘的映射关系
		map<char, string> tellphone = {
			   { '2', "abc" },{ '3', "def" },
			   { '4', "ghi" },{ '5', "jkl" },
			   { '6', "mno" },{ '7', "pqrs"},
			   { '8', "tuv" },{ '9', "wxyz"},
		};
		// 当输入数字只有一位的处理
		vector<string> ans = {};
		for (int i = 0; i < tellphone[digits[0]].size(); i++) {
			string temp;
			temp.push_back(tellphone[digits[0]][i]);
			ans.push_back(temp);
		}
		// 当大于等于两位数字的处理
		for (int i = 1; i < digits.size(); i++) {
			vector<string> new_ans = {}; // 初始化新的 结果

			// 把前n步找到所有组合 与 下一组号码组进行组合
			for (int j = 0; j < tellphone[digits[i]].size(); j++) {
				for (auto x : ans) {
					new_ans.push_back(x + tellphone[digits[i]][j]);				
				}
			}			
			ans = new_ans; // 新的组合赋值旧组合
		}		
		return ans;
	}
};
int main() {
	string digits = { "233" };
	Solution solv;
	auto ans = solv.letterCombinations(digits);
	sort(ans.begin(), ans.end());
	cout << ans << endl;
	return 0;
}

回溯法解答

代码

class Solution {
    private String[] maps = new String[]{"abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
    private List<String> answer = new ArrayList<>();

    public List<String> letterCombinations(String digits) {
        if (digits.length() == 0) return answer;
        recuir(digits, "");
        return answer;
    }
    // 递归
    // digits 代表还没有用到的电话数字, temp是已经尝试过来的字符串
    public void recuir(String digits, String temp) {
        if (digits.length() == 0) answer.add(temp);
        else {
            String newDigits = digits.substring(1);
            
            // 找出单个数字所映射的字符串
            int num = Integer.parseInt(digits.substring(0, 1));
            String str = maps[num - 2];
            
            // 回溯部分
            for (int i = 0; i < str.length(); i++) {
                String newTemp = temp + str.substring(i, i + 1);
                recuir(newDigits, newTemp);
            }
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值