[剑指-Offer] 55 - I. 二叉树的深度及II. 平衡二叉树(二叉树、后序遍历、代码优化、巧妙解法)

1. 题目来源

链接:I. 二叉树的深度
链接:II. 平衡二叉树
来源:LeetCode——《剑指-Offer》专项

2. 题目说明

在这里插入图片描述
在这里插入图片描述

3. 题目解析 — I. 二叉树的深度

方法一:递归+常规解法

从根节点开始遍历:

  • 若仅有根节点,则深度为 1
  • 若根节点只有左子树没有右子树,则深度为左子树深度 +1
  • 若根节点只有右子树没有左子树,则深度为左子树深度 +1
  • 若左右子树均存在,则该树的深度为其左子树、右子树的深度的较大值再 +1

这样就可以采用递归的思路进行实现了。

参见代码如下:

// 执行用时 :16 ms, 在所有 C++ 提交中击败了46.43%的用户
// 内存消耗 :21.4 MB, 在所有 C++ 提交中击败了100.00%的用户

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int maxDepth(TreeNode* root) {
        if (root == nullptr) return 0;
        int left = maxDepth(root->left);
        int right = maxDepth(root->right);
        return (left > right) ? (left + 1) : (right + 1);
    }
};

4. 题目解析 — II. 平衡二叉树

方法一:递归+常规解法

有了求二叉树的深度的经验之后再解决这个问题,我们很容易就能想到一个思路:

  • 在遍历树的每个结点的时候,调用函 maxDepth 得到它的左右子树的深度
  • 如果每个结点的左右子树的深度相差都不超过 1,按照定义它就是一棵平衡的二叉树。

参见代码如下:

// 执行用时 :16 ms, 在所有 C++ 提交中击败了79.85%的用户
// 内存消耗 :22.7 MB, 在所有 C++ 提交中击败了100.00%的用户

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool isBalanced(TreeNode* root) {
        if (root == nullptr) return true;
        int left = maxDepth(root->left);
        int right = maxDepth(root->right);
        int diff = left - right;
        if (diff > 1 || diff < -1) return false;

        return isBalanced(root->left) and isBalanced(root->right);
    }

    int maxDepth(TreeNode* root) {
        if (root == nullptr) return 0;
        int left = maxDepth(root->left);
        int right = maxDepth(root->right);
        return (left > right) ? (left + 1) : (right + 1);
    }
};

方法二:递归优化+巧妙解法

以上面的方法,代码固然简洁,但我们也要注意到该递归使得一个结点会被重复遍历多次,这种思路的时间效率不高。
在这里插入图片描述
在这里插入图片描述
后序遍历:当使用后序遍历的时候,遍历到一个节点之前,就已经遍历了它的左右子树,只要在遍历每个节点的时候记录它的深度(某一节点的深度等于它到叶节点的路径的长度),我们就能够一边遍历一边判断每个结点是不是平衡的。

// 执行用时 :12 ms, 在所有 C++ 提交中击败了93.83%的用户
// 内存消耗 :23.7 MB, 在所有 C++ 提交中击败了100.00%的用户

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool isBalanced(TreeNode* root) {
        int depth = 0;
        return help(root, &depth);
    }

    bool help(TreeNode* root, int* pDepth) {
        if (root == nullptr) {
            *pDepth = 0;
            return true;
        }
        int left;
        int right;
        if (help(root->left, &left) and help(root->right, &right)) {
            int diff = left - right;
            if (diff <= 1 and diff >= -1) {
                *pDepth = 1 + (left > right ? left : right);
                return true;
            }
        }
        return false;
    }
};
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Ypuyu

如果帮助到你,可以请作者喝水~

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

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

打赏作者

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

抵扣说明:

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

余额充值