二叉树_题目10:110. 平衡二叉树

91 阅读3分钟

题目10:110. 平衡二叉树

110. 平衡二叉树

同类题目

前置知识

题目描述

给定一个二叉树,判断它是否是

平衡二叉树

示例 1:

 输入:root = [3,9,20,null,null,15,7]
 输出:true

示例 2:

 输入:root = [1,2,2,3,3,null,null,4,4]
 输出:false

示例 3:

 输入:root = []
 输出:true

提示:

  • 树中的节点数在范围 [0, 5000]
  • -104 <= Node.val <= 104

思路分析

本题使用子问题分解(分治)思想来求解

首先考虑,如果单独抽出一个二叉树节点,它需要做什么事情?需要在什么时候(前/中/后序位置)做?其他的节点交给框架,递归函数会帮你在所有节点上执行相同的操作。

本题要返回左右子树的高度后,进行比较高度的差值,如果大于1,则不是平衡二叉树,因此是后续位置。

针对某一个单独的节点,有哪些事情要做?

  • 比较左右子树返回的高度是否大于1
  • 返回1 + max(leftheight, rightheight)

程序代码

方法一:使用一个全局变量记录是否是平衡树

 //https://leetcode.cn/problems/balanced-binary-tree/description/
 //110. 平衡二叉树
 #include<iostream>
 #include<vector>
 using namespace std;
 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 {
 private:
     bool balance = true;
 public:
     int travel(TreeNode* root)
     {
         if(root == nullptr)
         {
             return 0;
         }
 ​
         int leftdep = travel(root->left);
         int rightdep = travel(root->right);
         // 如果左右的深度大于1 则记录不是平衡树
         if(abs(leftdep - rightdep) > 1)
         {
             balance = false;
         }
 ​
         return 1 + max(leftdep,rightdep);
 ​
     }
     bool isBalanced(TreeNode* root) {
         travel(root);
         return balance;
     }
 };

复杂度分析

时间复杂度O(n),其中n是二叉树中的节点个数。使用自底向上的递归,每个节点的计算高度和判断是否平衡都只需要处理一次,最坏情况下需要遍历二叉树中的所有节点,因此时间复杂度是 O(n)

空间复杂度O(n),其中 n 是二叉树中的节点个数,二叉树最坏情况下退化为单链表。

程序代码

方法二:使用一个特殊值-1,记录是否是平衡树

 class Solution {
 public:
     int travel(TreeNode* root)
     {
         if(root == nullptr)
         {
             return 0;
         }
         
         int leftdep = travel(root->left);
         int rightdep = travel(root->right);
         // 如果不是平衡树大于1,则返回-1
         if(leftdep == -1 || rightdep == -1 || abs(leftdep - rightdep) > 1)
         {
             return -1;
         }
         // 返回子树的高度
         return 1 + max(leftdep,rightdep);
 ​
     }
     bool isBalanced(TreeNode* root) {
         return travel(root) != -1;     
     }
 };

程序代码

方法三:判断left 后,如果为-1 可以提前退出

 class Solution {
 public:
     int travel(TreeNode* root)
     {
         if(root == nullptr)
         {
             return 0;
         }
 ​
         int leftdep = travel(root->left);
         // 左子树如果是-1,可以直接退出了,不需要继续递归
         if(leftdep == -1 )
         {
             return -1;
         }
         int rightdep = travel(root->right);
 ​
         if(rightdep == -1 || abs(leftdep - rightdep) > 1)
         {
             return -1;
         }
 ​
         return 1 + max(leftdep,rightdep);
 ​
     }
     bool isBalanced(TreeNode* root) {
         return travel(root) != -1;
        
     }
 };

三次优化后的时间提升很明显

题目感悟

最初的方法中一直纠结怎么不使用全局变量,在递归的函数中直接判断,因为全局变量一个很多的缺点是要全部都跑一遍,最后才能判断出来结果,时间就上去了。

方法二中使用了一个特殊的值,解决了这个问题,能够提前返回后,程序就快了很多。

更多相关知识:github.com/pingguo1987…