树:BFS,DFS解Leetcode电话号码的字母组合问题

问题描述:

题目:Leetcode 第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'] 的一个数字。

BFS解法:

这道题我们可以把字母逐个排列组合的过程,看成一棵,如图:

实际上这就很像一颗n叉树 。借用二叉树BFS的知识我们一行一行的遍历,便可以组出来。

二叉树BFS代码:

void levelorder(TreeNode tree)
	{
		//借用一个队列做辅助
		queue<TreeNode> res;
		res.push(tree);
		while (!res.empty())
		{
			TreeNode temp = res.front();
			res.pop();
			//这里可以加一步,即访问temp
			//遍历当前节点的左子节点和右子节点
			if (temp.left != NULL)
				res.push(temp.left);
			if (temp.right != NULL)
				res.push(temp.right);
		}
	}

因为最多有两个子节点所以是二叉树,如果最多有n个子节点我们可以称它为n叉树, 那么n叉树的子节点比较多,我们不可能一次性全部写完,可以使用for循环来遍历, 代码如下:

void levelorder(TreeNode root)
	{
		//借用一个队列做辅助
		queue<TreeNode> res;
		res.push(root);
		while (!res.empty())
		{
			TreeNode temp = res.front();
			res.pop();
			//这里可以加一步,即访问temp
			//再遍历当前节点的所有子节点
			for (int i = 0;i < temp.child.count;i++)//temp.child.count表示temp子代数量
				res.push(temp.child[i]);
		}
	}

搞懂了上面的代码,我们来看看这道题。这道题中的树是我们想象的,那我们怎么确定走到叶子节点了呢?其实如果有n个 数字,那么叶子节点字符串的长度就应该是n。

最终代码:

class Solution {
public:
    vector<string> letterCombinations(string digits) 
    {
        int n=digits.size();
        vector<string> v;
        queue<string> res;
        res.push("");
        if(n==0)
        {
            return v;
        }
        //str1储存电话键上的数字对应的所有字符串
        vector<string> str1={"abc","def","ghi",
                    "jkl","mno","pqrs",
                    "tuv","wxyz"};
        while(res.front().size()!=n)
        {
            string temp=res.front();
            res.pop();
            //digits.at(temp.size())-'2' 表示 digits上每个数 在电话键上对应的字符串
            //其中-'2'是因为要将digits上的字符转换成对应的数同时此数还要和str1里对应字符串下标对应
            //str2 就相当于 temp的子代
            string str2=str1[digits.at(temp.size())-'2'];
            for(int i=0;i<str2.size();i++)
            {
                res.push(temp+str2[i]);
            }
        }
        int m=res.size();
        for(int i=0;i<m;i++)
        {
            v.push_back(res.front());
            res.pop();
        }
        return v;

    }
};

DFS解法:

除了BFS自然会想到DFS,特殊的是这里往回走的时候并不需要撤销选 择,因为字符串每次都会生成一个新的对象。

具体代码:

class Solution {
public:

    queue<string> res;
    void DFS( string digits, string str, vector<string>& str1, int index)
    {
	if (str.size() == digits.size())
	{
        //到叶子节点了,就把这条路径选择的字符添加到res中
		res.push(str);
	}
	else
	{
		string str2 = str1[digits.at(index) - '2'];
        //访问当前节点的所有子节点
		for (int i = 0;i < str2.size();i++)
		{
			DFS( digits, str + str2[i], str1, index + 1);
		}
	}
    /**
    *  res
    *  index 表示访问到第几个数字了,也可以认为访问到树的第几层了
    *  digits
    *  tab
    *  path 从根节点到叶子结点的路径
    */

    }
    vector<string> letterCombinations(string digits)
    {
	int n = digits.size();
	vector<string> v;
	if (n == 0)
	{
		return v;
	}
	//str1储存电话键上的数字对应的所有字符串
	vector<string> str1 = { "abc","def","ghi",
				"jkl","mno","pqrs",
				"tuv","wxyz" };
	DFS( digits, "", str1, 0);
	int m = res.size();
	for (int i = 0;i < m;i++)
	{
		v.push_back(res.front());
		res.pop();
	}
	return v;


    }
};

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

别抢我的辣条~

老板大气!祝老板身体健康!!!

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

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

打赏作者

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

抵扣说明:

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

余额充值