「这是我参与2022首次更文挑战的第28天,活动详情查看:2022首次更文挑战」
前言
每天至少一道算法题,死磕算法
我们为什么需要平衡二叉树?
平衡二叉树是特殊的二叉树,面试中考二叉树,就经常考特殊的二叉树,因为特殊的二叉树用处才大,我们先来看一下二叉平衡术的用途
图一
这棵就是平衡二叉树
图二
这棵就不是
如果我们要查询val为1的话,图一需要几步?3步妥妥的
图二呢,数了半天,需要5步
所以平衡二叉树能够缩短我们的查询时间
接下来我们复习一下二叉平衡树的定义。
平衡二叉树是任意结点的左右子树高度差绝对值都不大于1的二叉搜索树。
抓住其中的三个关键字:
- 任意结点
- 左右子树高度差绝对值都不大于1
- 二叉搜索树
发现这些关键字都是我们熟悉的东西,那么题目应该也不太难做
题目
这是leetcode上的第110道题目110. 平衡二叉树
给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为:
一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。
示例 1:
输入:root = [3,9,20,null,null,15,7] 输出:true
思路
- 第一步从题目中提取关键字
一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。 这句话怎么这么熟悉,这不就是昨天我们写的那个生成二叉搜索树那到题目么,他其实就是一个高度平衡二叉树
只要有关联,那么今天这道题目肯定就好写了
需要注意的是,我们这里的二叉平衡树和真正的二叉平衡树的定义是不一样的,屏幕中给出的定义是一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。没有说是二叉搜索树,所以我们没有必要验证是不是二叉搜索树,ღ( ´・ᴗ・` )比心
- 第二点分析
我们要判断左右两个子树的高度差的绝对值不超过 1 。其实就是判断每个节点的左右子树的高度的绝对值的差值大不大于1,所以我们就递归求高度好了,我们以前学层序遍历的时候,学过求高度的方法,但是层数遍历复杂度太高了,直接O(n^2)了,所以今天我们在教一个逆向思维求高度的方法,也被称为自底向上求递归
function getHeight(root){
// 如果不存在高度为0
if(!root){
return 0;
}
const left = getHeight(root.left);
const right = getHeight(root.right);
return Math.max(left,right)+1;
}
有了这个方法,我们在加一下flag和判断高度绝对值的方法就结束了
题解
var isBalanced = function(root) {
let flag = true;
const getHeight = function(root){
// root为null,或者flag=false,那么就不用执行了,直接返回高度0
if(!root||!flag){
return 0;
}
let left = getHeight(root.left);
let right = getHeight(root.right);
if(Math.abs(left-right)>1){
flag = false;
}
// 逆想思维求高度
return Math.max(left,right)+1;
}
getHeight(root);
return flag;
};
- 时间复杂度:O(n),其中n为二叉树的节点个数。因为每个节点都会处理一次
- 空间复杂度:O(n),空间复杂度主要取决于递归调用的层数,如果是一个一直只有左节点的树,那么空间复杂度最大为n