[剑指-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;
    }
};
发布了343 篇原创文章 · 获赞 197 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/yl_puyu/article/details/104756110