leetcode513.找树左下角的值与leetcode17.电话号码的字母组合

回溯

回溯的本质是穷举,穷举所有可能,然后选出我们想要的答案。

关于回溯的理解和本质在之前已经讲过,今天做了几道题目,对于其中两道找左下角的值和电话号码的字母组合都用到了回溯。其实找左下角的值利用层序遍历更加简单和直观,但是为了增加对递归的理解,用递归做也是可以的。


回溯(递归)三步

  1. 确定返回值和参数

对于电话号码这道题,虽然是字符串,但是可以抽象成树形结构。

  首先需要一个字符串s来收集叶子节点的结果,然后用一个字符串数组res保存起来,这两个变量我依然定义为全局。

再来看参数,参数指定是有题目中给的string digits,然后还要有一个参数就是int型的index。

注意这个index可不是 77.组合 (opens new window)216.组合总和III (opens new window)中的startIndex了。

这个index是记录遍历第几个数字了,就是用来遍历digits的(题目中给出数字字符串),同时index也表示树的深度。

//设置全局列表存储最后的结果
    List<String> list = new ArrayList<>();

//比如digits如果为"23",num 为0,则str表示2对应的 abc
    public void backTracking(String digits, String[] numString, int num)

对于左下角的值,其实题目的本质就是求最大深度的最左边的值。当用DFS遍历时不会涉及对中间节点的处理逻辑。所以前中后序都是可以的。因为无论前中后序,都是先遍历左再遍历右(节点)。其最大深度用Deep作为全局变量,值用value记录。参数为根节点和每次遍历的深度。

private int Deep = -1;
private int value = 0;
private void findLeftValue (TreeNode root,int deep) 

2、回溯(递归)终止条件

对于电话号码这道题目,当记录的num长度和传入的字符串长度相同时,递归结束。

此时,需要进行记录路径字符数组。

//遍历全部一次记录一次得到的字符串
        if (num == digits.length()) {
            list.add(temp.toString());
            return;
        }

左下角的值则可以理解为到叶子节点则递归终止。

if (root == null) return;
        if (root.left == null && root.right == null) {
            if (deep > Deep) {
                value = root.val;
                Deep = deep;
            }
        }

3、递归&回溯逻辑

对于电话号码的这道题。不像二叉树这种天然的二分树,这道题需要自己拆分循环次数,因此在递归前应该先找到循环次数,对于这道题,循环次数就是当前数字对应的字母字符个数。进入循环后即需要添加当前的字符而后进入递归,递归需要弹出递归前加入的字符。目的:找到所有字符的组成。

String str = numString[digits.charAt(num) - '0'];
        for (int i = 0; i < str.length(); i++) {
            temp.append(str.charAt(i));
            //c
            backTracking(digits, numString, num + 1);
            //剔除末尾的继续尝试
            temp.deleteCharAt(temp.length() - 1);
        }

对于左下角值这个题目来说,每次递归都需要判断递归的下一节点是否为空来避免空指针异常。其次递归前需要将deep+1,递归结束后,需要弹出该深度。目的:遍历所有深度。

if (root == null) return;
        if (root.left == null && root.right == null) {
            if (deep > Deep) {
                value = root.val;
                Deep = deep;
            }
        }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,下面是电话号码字母组合问题的 C++ 代码实现: ``` class Solution { public: vector<string> letterCombinations(string digits) { unordered_map<char, string> mapping = { {'2', "abc"}, {'3', "def"}, {'4', "ghi"}, {'5', "jkl"}, {'6', "mno"}, {'7', "pqrs"}, {'8', "tuv"}, {'9', "wxyz"} }; vector<string> res; if (digits.empty()) { return res; } string combination; backtrack(res, combination, digits, 0, mapping); return res; } void backtrack(vector<string>& res, string& combination, string& digits, int index, unordered_map<char, string>& mapping) { if (index == digits.size()) { res.push_back(combination); return; } for (char c : mapping[digits[index]]) { combination.push_back(c); backtrack(res, combination, digits, index + 1, mapping); combination.pop_back(); } } }; ``` 其中 `letterCombinations` 函数用来生成所有的字母组合,`backtrack` 函数用来进行回溯操作。在 `letterCombinations` 函数中,首先根据数字字符和字母的映射关系创建了一个 `unordered_map` 对象 `mapping`。然后定义了一个空字符串 `combination` 和一个空 vector `res` 来保存最终结果。最后调用了 `backtrack` 函数来生成所有的字母组合。在 `backtrack` 函数中,首先判断是否达到了数字字符串的末尾,如果是,则将当前的 `combination` 字符串保存到 `res` 中。否则,遍历当前数字字符所能表示的所有字母,依次加入到 `combination` 字符串中,然后递归调用 `backtrack` 函数,添加下一个数字字符所能表示的字母。递归完成后,需要将 `combination` 字符串还原到上一个状态,以便进行下一次回溯。最终返回 `res` 数组即可。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值