力扣257. 二叉树的所有路径

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

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

class Solution {
public:
    //能进入countPath中,说明该节点不为nullptr
    void countPath(TreeNode* cur, vector<int>& path, vector<string>& result){
        //把当前遍历到的二叉树节点的值放入到path中,因为当前遍历到的节点是当前路径中的一个节点
        path.push_back(cur->val);
        //递归结束条件
        //如果遍历到孩子节点,说明找到了一条完整的路径
        if(cur->left == nullptr && cur->right == nullptr){
            //n表示当前path中的节点数有多少
            int n = path.size();
            string curPath = "";    //curPath表示当前找到的路径的字符串形式,先初始化为空串
            //假设当前 path 中的值为1,2,5
            //for循环将每一个数字后面紧跟着一个 "->" 符号,由于 5 后面没有 "->" ,所以for循环只遍历到 2 的位置。
            for(int i = 0; i < n-1; ++i){
                curPath += to_string(path[i]);
                curPath += "->";
            }
            //由于上面的for循环没有将 5 放入到当前找到的路径的字符串形式中,所以要把 5 加进去
            curPath += to_string(path[n-1]);
            //这样curPath就是当前遍历到的路径的完整字符串形式将他放入到结果集中
            result.push_back(curPath);
        }
        //如果当前节点存在左孩子,就向左进行遍历
        if(cur->left){
            countPath(cur->left, path, result);
            //回溯和递归是一一对应的,有一个递归,就要有一个回溯
            path.pop_back();//回溯,为了回到上一次进行递归的节点
        }
        //如果当前节点存在左孩子,就向左进行遍历
        if(cur->right){
            countPath(cur->right, path, result);
            path.pop_back();
        }
    }
    vector<string> binaryTreePaths(TreeNode* root) {
        vector<int> path;//存放当前遍历的路径上的各节点值
        vector<string> result;//存放每一条路径的字符串,形如"1->2->5"
        //如果我们给定的二叉树的根节点为空,我们直接返回
        if(root == nullptr){
            return result;
        }
        //如果给定的二叉树不为空,进入函数
        countPath(root, path, result);
        //返回结果数组
        return result;
    }
    // 时间复杂度:O(N^2),其中N表示节点数目。在深度优先搜索中每个节点会被访问一次且只会被访问一次,path数组进行遍历,时间代价为O(N),故时间复杂度为O(N2)。
    // 空间复杂度:O(N^2),其中N表示节点数目。除答案数组外我们需要考虑递归调用的栈空间。在最坏情况下,当二叉树中每个节点只有一个孩子节点时,即整棵二叉树呈一个链状,此时递归的层数为N,此时每一层的path变量的空间代价的总和为O(N^2)空间复杂度为O(N2)。最好情况下,当二叉树为平衡二叉树时,它的高度为log N,此时空间复杂度为O((log N)^2)。
};

简洁形式,隐藏了回溯的过程。

class Solution {
public:
    void countPath(TreeNode* cur, string path, vector<string>& result){
        path += to_string(cur->val);
        if(cur->left == nullptr && cur->right == nullptr){
            result.push_back(path);
        }
        if(cur->left){
            countPath(cur->left, path+"->", result);
        }
        if(cur->right){
            countPath(cur->right,path+"->",result);
        }
    }
    vector<string> binaryTreePaths(TreeNode* root) {
        vector<string> result;
        string path;
        if(root == nullptr){
            return result;
        }
        countPath(root, path, result);
        return result;
    }
};

注意在函数定义的时候void countPath(TreeNode* cur, string path, vector<string>& result) ,定义的是string path,每次都是复制赋值,不用使用引用,否则就无法做到回溯的效果。

那么在如上代码中,貌似没有看到回溯的逻辑,其实不然,回溯就隐藏在countPath(cur->left, path + "->", result);中的 path + "->" 每次函数调用完,path依然是没有加上"->" 的,这就是回溯了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值