LeetCode刷题笔记【12】:二叉树专题-4(平衡二叉树、二叉树的所有路径、左叶子之和)

前置知识

参考前文

参考文章:
LeetCode刷题笔记【9】:二叉树专题-1(分别用递归遍历、迭代遍历、标记遍历实现前、中、后序遍历)
LeetCode刷题笔记【10】:二叉树专题-2(二叉树的层序遍历、翻转二叉树、对称二叉树)
LeetCode刷题笔记【10.5】:二叉树专题-2.5(二叉树的层序遍历 - 10道题)
LeetCode刷题笔记【11】:二叉树专题-3(二叉树的最大深度、二叉树的最小深度、完全二叉树的节点个数)

110.平衡二叉树

题目描述

在这里插入图片描述

LeetCode链接:https://leetcode.cn/problems/balanced-binary-tree/description/

自顶向下法

设置一个函数depth用于求当前节点的高度;
主函数isBalanced深度遍历整个树, 对每个节点都用depth检查其左右子树的高度是否符合要求.

class Solution {
public:
    int depth(TreeNode* node){
        if(node==nullptr)
            return 0;
        return max(depth(node->left), depth(node->right)) + 1;
    }
    bool isBalanced(TreeNode* root) {
        if(root==nullptr) return true;
        if( abs(depth(root->left) - depth(root->right)) <= 1)
            return isBalanced(root->left)&&isBalanced(root->right);
        return false;
    }
};

自底向上法

上述方法也可以实现, 但整个过程是"自顶向下"的, 悲观情况下对每个节点都需要调用多遍depth函数
如果是自底向上的, 对每个节点就只需要调用一次depth

class Solution {
public:
    int depth(TreeNode* node){
        if(node==nullptr)
            return 0;
        int leftDepth = depth(node->left);
        int rightDepth = depth(node->right);
        if(leftDepth==-1 || rightDepth==-1 || abs(leftDepth-rightDepth)>1)
            return -1;
        return max(leftDepth, rightDepth)+1;
    }
    bool isBalanced(TreeNode* root) {
        return depth(root)!=-1;
    }
};

最好瞅一眼LeetCode题解中的动态过程, 感受更深.

参考的LeetCode题解: https://leetcode.cn/problems/balanced-binary-tree/solutions/377216/ping-heng-er-cha-shu-by-leetcode-solution/

257. 二叉树的所有路径

题目描述

在这里插入图片描述

LeetCode链接:https://leetcode.cn/problems/binary-tree-paths/description/

解题思路

思路: 递归实现, 递归过程中维护一个string
递归到叶子节点的时候将string加入vector<string> ans

代码

class Solution {
private:
    vector<string> ans;
public:
    void helper(TreeNode* node, string str){
        str += to_string(node->val);
        if(node->left==nullptr && node->right==nullptr){
            ans.push_back(str);
            return;
        }else{
            str += "->";
            if(node->left)  helper(node->left, str);
            if(node->right) helper(node->right, str);
        }
        return;
    }
    vector<string> binaryTreePaths(TreeNode* root) {
        if(root==nullptr)
            return ans;
        string str;
        helper(root, str);
        return ans;
    }
};

404.左叶子之和

题目描述

在这里插入图片描述

LeetCode链接:https://leetcode.cn/problems/sum-of-left-leaves/description/

解题思路

进行深度优先遍历, 在过程中通过函数传参, 记录当前节点是左节点还是右节点
如果当前节点是叶子节点, 就检查是否是左节点, 左节点就加入ans

代码

class Solution {
private:
    int ans=0;
public:
    void helper(TreeNode* root, bool isLeft){
        if(root==nullptr)
            return;
        if(root->left==nullptr && root->right==nullptr){// 如果是叶子节点
            if(isLeft)// 并且还是一个左节点
                ans += root->val;//计入ans
            return;
        }
        if(root->left)  helper(root->left, true);// 检查左子树
        if(root->right) helper(root->right, false);// 检查右子树
        return;
    }
    int sumOfLeftLeaves(TreeNode* root) {
        helper(root, false);
        return ans;
    }
};

ps: 这里贴一下LeetCode官方给的题解吧, 思路是一样的.
感觉它写的很简洁, 或许执行起来会比我更快, 但是个人认为可读性不是很直观(比起我的直接传参);

class Solution {
public:
    bool isLeafNode(TreeNode* node) {
        return !node->left && !node->right;
    }

    int dfs(TreeNode* node) {
        int ans = 0;
        if (node->left) {
            ans += isLeafNode(node->left) ? node->left->val : dfs(node->left);
        }
        if (node->right && !isLeafNode(node->right)) {
            ans += dfs(node->right);
        }
        return ans;
    }

    int sumOfLeftLeaves(TreeNode* root) {
        return root ? dfs(root) : 0;
    }
};
作者:力扣官方题解
链接:https://leetcode.cn/problems/sum-of-left-leaves/solutions/419103/zuo-xie-zi-zhi-he-by-leetcode-solution/
来源:力扣(LeetCode)

总结

二叉树的题目普遍都有递归法和迭代法, 目前时间有限, 就先掌握递归法吧;
如果当天有时间精力, 或许可以折腾一下迭代法.

并且在使用递归的时候, 需要有意识地思考这个递归放出去了以后, 其内部执行过程是怎样的, 从而计算其时间复杂度.
至于递归的终点(结束点)等内容就是基础了.

本文参考:
平衡二叉树
二叉树的所有路径
左叶子之和

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值