电话号码的字母组合

题目

在这里插入图片描述

思路

本题的难点之一是如何更好的将数字转换为相应的字母,一开始我的思路是使用hash,但是并不能很好的解决问题,如下图:
在这里插入图片描述
从上图中我们可以知道,我们的目的就是要找出所有到达叶节点的路径,换句话说就是当到达树的深度时,我们便回头,很明显这是回溯法类型的题目。那么分析以下本题存在的难点和相关知识点:

  • 首先,相对于传统的回溯法类型的题目,本道题是一个数字代表三个或者四个字母,我们要避免选到同一组的字母
  • 接着如何更好的将数字转换为相应的字母集合,如果使用哈希思想,那么怎样的哈希映射才是最方便的
  • 如何回溯

其实我们看,本道题相比较传统的回溯法类型的题目,难点和重点就是数字如何映射到相应的字母集合,先看代码:

class Solution {
public:
    vector<string> res;
	string path;
	vector<string> table{ "abc","def","ghi","jkl","mno","pqrs","tuv","wxyz" };
	void dfs(int& depth, string digits) {
		int n = digits.size();
		if (depth == n) {
			res.push_back(path);
			return;
		}

		for (unsigned int i = 0; i < table[digits[depth] - '2'].size(); i++) {
			path.push_back(table[digits[depth] - '2'][i]);
			depth += 1;
			dfs(depth, digits);
            depth -= 1;
			path.pop_back();
		}
	}
	vector<string> letterCombinations(string digits) {
		if (digits == "")
			return res;
		int depth = 0;
		dfs(depth, digits);
		return res;
		
	}
};

首先我们设置一个全局的容器变量,表示数字到字母的映射:

vector<string> table{ "abc","def","ghi","jkl","mno","pqrs","tuv","wxyz" };

接着就是深度搜索:

void dfs(int& depth, string digits) {
		int n = digits.size();
		if (depth == n) {
			res.push_back(path);
			return;
		}

		for (unsigned int i = 0; i < table[digits[depth] - '2'].size(); i++) {
			path.push_back(table[digits[depth] - '2'][i]);
			depth += 1;
			dfs(depth, digits);
            depth -= 1;
			path.pop_back();
		}
}

首先深度搜索函数具有两个参数,遍历到的深度,还有该深度的数字所对应字母集合的size大小,我们第一步先设置递归(回溯算法基本是运用递归算法)的基准条件,那么基准条件就是到达树的叶节点,也就是达到了树的深度;
接着就到了本道题的重点和难点:如何循环。那么我们之前设置了一个全局的容器变量,这里我们巧妙地利用此时遍历到地树的深度,和该映射容器相结合,树的深度代表遍历到了第几个数字,那么我们就可以映射到相对应地字母集合,如下面定义:

 table[digits[depth] - '2'].size();

我们解读一下,depth表示遍历到第几个数字,然后再将该位置地数字映射到相对应的字母集合。然后就是按照下图开始回溯:
在这里插入图片描述

下面介绍另外一种方法:广度优先
我们也可以这样解题:
设置一个队列,每遍历一个数字,我们就将队列中的元素逐个与该数字所对应的字母集合相结合,并再次放进队列中,如下图演示:
在这里插入图片描述
相关代码如下:

class Solution {
public:
    //bfs
    vector<string> letterCombinations(string digits) {
		vector<string> res;
		if (digits == "")
			return  res;
		deque<string> d;
		vector<string> table{ "abc","def","ghi","jkl","mno","pqrs","tuv","wxyz" };
		int n = digits.size();
		for (int i = 0; i < table[digits[0] - '2'].size(); i++) {
			string str;
			str.push_back(table[digits[0] - '2'][i]);
			d.push_back(str);
		}
		for (int i = 1; i < n; i++) {
			int len = d.size();
			while (len--) {
				for (int j = 0; j < table[digits[i] - '2'].size(); j++) {
                    string str = d.front();
					str += table[digits[i] - '2'][j];
					d.push_back(str);
				}
				d.pop_front();
			}
		}
		res.assign(d.begin(),d.end());
		return res;
	}
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值