力扣日记12.3-【二叉树篇】二叉树的所有路径

力扣日记:【二叉树篇】二叉树的所有路径

日期:2023.12.3
参考:代码随想录、力扣

257. 二叉树的所有路径

题目描述

难度:简单

给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。

叶子节点 是指没有子节点的节点。

示例 1:
在这里插入图片描述

输入:root = [1,2,3,null,5]
输出:[“1->2->5”,“1->3”]

示例 2:

输入:root = [1]
输出:[“1”]

提示:

  • 树中节点的数目在范围 [1, 100] 内
  • -100 <= Node.val <= 100

题解

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
   
#define SOLUTION 2
public:
#if SOLUTION == 1
    // 本体关键在于 递归+回溯
    // 如对于[1,2,3,null,5]这样的二叉树, 首先遍历了1-2-5后, 需要回溯到1-2, 再回溯到1, 再继续遍历1-3
    // 因此需要在每次递归后进行回溯(见代码)
    // 至于遍历, 由于是从根节点遍历到叶子节点, 因此使用前序遍历(中-左-右)
    vector<string> binaryTreePaths(TreeNode* root) {
   
        vector<int> path;
        vector<string> result;
        if (root == NULL) return result;
        traversal(root, path, result);
        return result;
    }
    // 递归参数与返回值:参数为当前节点,当前路径以及结果集;返回值为空
    void traversal(TreeNode* node, vector<int>& path, vector<string>& result) {
    // 注意是引用传递
        // 递归处理(这里中节点的处理要放在终止条件前,因为终止条件需返回包含叶子节点的路径)
        path.push_back(node->val);
        // 递归终止条件:当遇到叶子节点时,将path放入结果集并返回
        if (node->left == nullptr && node->right == nullptr) {
   
            // 将path里记录的路径转为string格式
            string sPath;
            for (int i = 0; i < path.size() - 1; i++) {
    
                sPath += to_string(path[i]);
                sPath += "->";
            }
            sPath += to_string(path[path.size() - 1]); // 记录最后一个节点(叶子节点)
            result.push_back(sPath); // 收集一个路径
            return;
        }
        // 左节点
        if (node->left) {
      // 防止叶子节点判断时为空
            traversal(node->left, path, result);
            path.pop_back();    // 回溯(遍历到叶子节点或左右节点都遍历了, 则要回溯到上一个节点)
        }
        if (node->right) {
   
            traversal(node->right, path, result);
            path.pop_back();    // 同理
        }
    }

#elif SOLUTION == 2 // 精简版
    vector<string> binaryTreePaths(TreeNode* root) {
   
        string path;
        vector<string> result;
        if (root == NULL) return result;
        traversal(root, path, result);
        return result;
    }
    // 这里直接用string,避免了vector<int>到string的转换
    void traversal(TreeNode* node, string path, vector<string> &result) {
   
        // 中
        path += to_string(node->val);
        // 终止条件
        if (node->left == nullptr && node->right == nullptr) {
   
            result.push_back(path);
            return;
        }
        // 递归处理
        if (node->left) {
   
            // 注意这里的参数为 path + "->", 而不是先将path = path + "->"再传入path
            // 同时string path也不是引用传递
            // 也就是当递归结束后, path 仍为原来的path, 而不是 path + "->",不用显式回溯"->"
            // 更不是完整路径(如果是引用传递则是如上面的完整路径),因此也不用显式回溯元素值
            traversal(node->left, path + "->", result);
        }
        if (node->right) {
   
            traversal(node->right, path + "->", result);
        }
    }
#endif
};

复杂度

时间复杂度:
空间复杂度:

思路总结

  • 本题关键在于 递归+回溯
    • 如对于[1,2,3,null,5]这样的二叉树, 首先遍历了1-2-5后, 需要回溯到1-2, 再回溯到1, 再继续遍历1-3
    • 因此需要在每次递归后进行回溯(见代码)
  • 至于遍历, 由于是从根节点遍历到叶子节点, 因此使用前序遍历(中-左-右)
  • 前序遍历以及回溯的过程示意图
    在这里插入图片描述
  • 在精简版代码中,之所以不用主动显式回溯
    • 是因为在递归函数的参数传递时,参数为 path + “->”, 而不是先将path = path + "->"再传入path
    • 同时string path也不是引用传递
    • 也就是当递归结束后, path 仍为原来的path, 而不是 path + “->”,不用显式回溯"->"
    • 更不是完整路径(如果是引用传递则是如上面的完整路径),因此也不用显式回溯元素值
  • 注意本次递归的中节点处理要放在终止条件之前,因为在终止条件时要存入包含此中节点的完整路径
  • 关于本题的迭代法,目前还未学习…二刷再补充

相关推荐

  1. [题解] 257. 所有路径

    2023-12-08 17:06:04       9 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-08 17:06:04       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-08 17:06:04       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-08 17:06:04       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-08 17:06:04       20 阅读

热门阅读

  1. [python高级编程]:01-数据结构

    2023-12-08 17:06:04       42 阅读
  2. 机器学习算法汇总--GBDT、XGBoost等

    2023-12-08 17:06:04       40 阅读
  3. c++的排序算法

    2023-12-08 17:06:04       29 阅读
  4. [linux] git lfs install 安装lfs

    2023-12-08 17:06:04       38 阅读
  5. redis的工具类详细

    2023-12-08 17:06:04       30 阅读
  6. 98765

    2023-12-08 17:06:04       34 阅读
  7. C++初学教程三

    2023-12-08 17:06:04       40 阅读
  8. RESTful API介绍,如何使用它构建 web 应用程序。

    2023-12-08 17:06:04       35 阅读
  9. vue遍历对象的几种方式

    2023-12-08 17:06:04       39 阅读
  10. 力扣1-100题解

    2023-12-08 17:06:04       25 阅读