代码随想录二刷 | 二叉树 | 110.平衡二叉树

代码随想录二刷 | 二叉树 | 110.平衡二叉树

题目描述

110.平衡二叉树

给定一个二叉树,判断它是否是高度平衡的二叉树。

本题中,一棵高度平衡二叉树定义为:

一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。

示例 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. 确定递归函数的参数和返回值

    参数:当前传入的节点

    返回值:因为求的是高度,所以为int

    如果当前传入节点为根节点的二叉树已经不是二叉平衡树了,还返回高度的话就没有意义了。

    所以如果已经不是二叉平衡树了,可以返回 -1 来标记已经不符合平衡树的规则了。

    cpp 复制代码
    int getHeight(TreeNode* node)
  2. 确定终止条件

    遇到空节点时终止,返回0,表示当前节点为根节点的树高度为 0

    cpp 复制代码
    if (node == NULL) {
    	return 0;
    }
  3. 确定单层递归的逻辑

    分别求出左右子树的高度,如果差值小于等于 1 ,则返回当前二叉树的高度,否则返回 -1,表示已经不是平衡二叉树了。

    cpp 复制代码
    int leftHeight = getHeight(node->left);
    if (leftHeight == -1) return -1;
    int rightHeight = getHeight(ndoe->right);
    if (rightHeight == -1) return -1;
    int result;
    if (abs(leftHeight - rightHeight) > 1) {
    	result = -1;	
    } else {
    	result = 1 + max(leftHeight, rightHeight);
    }
    return result;

迭代

本题的迭代方式可以先定义一个函数,专门用来求高度。

这个函数通过栈模拟的后序遍历找每一个节点的高度(其实是通过求传入节点为根节点的最大深度来求的高度)

cpp 复制代码
// cur节点的最大深度,就是cur的高度
int getDepth(TreeNode* cur) {
	stack<TreeNode*> st;
	if (cur != NULL) st.push(cur);
	int depth = 0; 
	int result = 0;
	while (!st.empty()) {
		TreeNode* node = st.top();
		if (node != NULL) {
			st.pop();
			st.push(node);
			st.push(NULL);
			depth++;
			if (node->right) st.push(node->right);
			if (node->left) st.push(node->left);
		} else {
			st.pop();
			node = st.top();
			st.pop();
			depth--;
		}
		result = result > depth ? result : depth;
	}
	return result;
}

然后再用栈来模拟后序遍历,遍历每一个节点的时候,再去判断左右孩子的高度是否符合,代码如下:

cpp 复制代码
bool isBalanced(TreeNode* root) {
	stack<TreeNode*> st;
	if (root == NULL) return true;
	st.push(root);
	while (!st.empty()) {
		TreeNode* node = st.top();
		st.pop();
		if (abs(getDepth(node->left) - getDepth(node->right)) > 1) {
			return fasle;
		}
		if (node->right) st.push(node->right);
		if (node->left) st.push(node->left);
	}
	return true;
}

当然此题用迭代法,其实效率很低,因为没有很好的模拟回溯的过程,所以迭代法有很多重复的计算。

虽然理论上所有的递归都可以用迭代来实现,但是有的场景难度可能比较大。

例如:都知道回溯法其实就是递归,但是很少人用迭代的方式去实现回溯算法!

因为对于回溯算法已经是非常复杂的递归了,如果再用迭代的话,就是自己给自己找麻烦,效率也并不一定高。

代码实现

递归法

cpp 复制代码
class Solution {
public:
	int getHeight(TreeNode* node) {
		if (node == NULL) return 0;
		int leftHeight = getHeight(node->left);
		if (leftHeight == -1) return -1;
		int rightHeight = getHeight(node->right);
		if (rightHeight == -1) return -1;
		return abs(leftHeight - rightHeight) > 1 ? -1 : 1 + max(leftheight, rightHeight);
	}
    bool isBalanced(TreeNode* root) {
        return getHeight(root) == -1 ? false : true;
    }
};

迭代法

cpp 复制代码
class Solution {
public:
class Solution {
private:
    int getDepth(TreeNode* cur) {
        stack<TreeNode*> st;
        if (cur != NULL) st.push(cur);
        int depth = 0; // 记录深度
        int result = 0;
        while (!st.empty()) {
            TreeNode* node = st.top();
            if (node != NULL) {
                st.pop();
                st.push(node);                          // 中
                st.push(NULL);
                depth++;
                if (node->right) st.push(node->right);  // 右
                if (node->left) st.push(node->left);    // 左

            } else {
                st.pop();
                node = st.top();
                st.pop();
                depth--;
            }
            result = result > depth ? result : depth;
        }
        return result;
    }

public:
    bool isBalanced(TreeNode* root) {
        stack<TreeNode*> st;
        if (root == NULL) return true;
        st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top(); 
            st.pop();
            if (abs(getDepth(node->left) - getDepth(node->right)) > 1) {
                return false;
            }
            if (node->right) st.push(node->right);           // 右(空节点不入栈)
            if (node->left) st.push(node->left);             // 左(空节点不入栈)
        }
        return true;
    }
};
相关推荐
刚学HTML22 分钟前
leetcode 05 回文字符串
算法·leetcode
蜀黍@猿25 分钟前
【C++ 基础】从C到C++有哪些变化
c++
Am心若依旧40927 分钟前
[c++11(二)]Lambda表达式和Function包装器及bind函数
开发语言·c++
zh路西法37 分钟前
【C++决策和状态管理】从状态模式,有限状态机,行为树到决策树(一):从电梯出发的状态模式State Pattern
c++·决策树·状态模式
冠位观测者1 小时前
【Leetcode 每日一题】2545. 根据第 K 场考试的分数排序
数据结构·算法·leetcode
轩辰~1 小时前
网络协议入门
linux·服务器·开发语言·网络·arm开发·c++·网络协议
lxyzcm1 小时前
C++23新特性解析:[[assume]]属性
java·c++·spring boot·c++23
蜀黍@猿1 小时前
C/C++基础错题归纳
c++
古希腊掌管学习的神2 小时前
[LeetCode-Python版]相向双指针——611. 有效三角形的个数
开发语言·python·leetcode
雨中rain2 小时前
Linux -- 从抢票逻辑理解线程互斥
linux·运维·c++