leetcode 110 学习笔记(判断平衡二叉树)

110.平衡二叉树

问题描述

传送门
在这里插入图片描述

思路

平不平衡看高度,不是深度。

先理解一个概念:

  1. 二叉树节点的深度:从根节点到该节点的最长简单路径边的条数。
  2. 二叉树节点的高度:从该节点到叶子节点的最长简单路径边的条数。

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

1、递归

① 明确递归函数的参数和返回值

参数的话为传入的节点指针,就没有其他参数需要传递了,返回值要返回传入节点为根节点树的深度。

那么如何标记左右子树是否差值大于1呢。

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

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

	// -1 表示已经不是平衡二叉树了,否则返回值是以该节点为根节点树的高度
	int getDepth(TreeNode* node)  

② 明确终止条件

递归的过程中,遇到空节点,终止返回0,表示当前节点为根节点的高度为0。

代码如下:

	if (node == NULL) {
	    return 0;
	}

③ 明确单层递归的逻辑

如何判断当前传入节点为根节点的二叉树是否是平衡二叉树呢, 当然是左子树高度和右子树高度相差。

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

代码如下:

	int leftDepth = depth(node->left); // 左
	if (leftDepth == -1) 
		return -1;     
	int rightDepth = depth(node->right); // 右
	if (rightDepth == -1) 
		return -1;
	
	int result;
	if (abs(leftDepth - rightDepth) > 1) {  // 中
	    result = -1;
	} else {
	    result = 1 + max(leftDepth, rightDepth); // 以当前节点为根节点的最大高度
	}
	
	return result;

代码精简之后如下:

	int leftDepth = getDepth(node->left);
	if (leftDepth == -1)
		 return -1;     
	int rightDepth = getDepth(node->right);
	if (rightDepth == -1) 
		return -1;
	return abs(leftDepth - rightDepth) > 1 ? -1 : 1 + max(leftDepth, rightDepth);

此时递归的函数就已经写出来了。

这个递归的函数传入节点指针,返回以该节点为根节点的二叉树的高度。

如果不是二叉平衡树,就返回-1。

getDepth整体代码如下:

	int getDepth(TreeNode* node) {
	    if (node == NULL) {
	        return 0;
	    }
	    int leftDepth = getDepth(node->left);
	    if (leftDepth == -1) 
	    	return -1;
	    int rightDepth = getDepth(node->right);
	    if (rightDepth == -1) 
	    	return -1;
	    return abs(leftDepth - rightDepth) > 1 ? -1 : 1 + max(leftDepth, rightDepth);
	}

最后本题整体递归代码如下:

	class Solution {
	public:
	    // 返回以该节点为根节点的二叉树的高度,如果不是二叉搜索树了则返回-1
	    int getDepth(TreeNode* node) {
	        if (node == NULL) {
	            return 0;
	        }
	        int leftDepth = getDepth(node->left);
	        if (leftDepth == -1) 
	        	return -1; // 说明左子树已经不是二叉平衡树
	        int rightDepth = getDepth(node->right);
	        if (rightDepth == -1) 
	        	return -1; // 说明右子树已经不是二叉平衡树
	        return abs(leftDepth - rightDepth) > 1 ? -1 : 1 + max(leftDepth, rightDepth);
	    }
	    bool isBalanced(TreeNode* root) {
	        return getDepth(root) == -1 ? false : true; 
	    }
	};

2、迭代

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

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

深度来求的高度)

代码如下:

	     // 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;
	}

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

	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;
	}

整体代码如下:

	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;
	    }
	};

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

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

总结

通过本题可以了解求二叉树深度 和 二叉树高度的差异。

求深度适合用前序遍历,求高度适合用后序遍历。

本题迭代法其实有点复杂,不一定说非要写出来。

但是递归方式是一定要掌握的!

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

晓梦林

都看到这里了,支持一下作者呗~

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

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

打赏作者

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

抵扣说明:

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

余额充值