树的理解(一):树的高度

树的高度

树的高度的递归思想:
根据树的高度的定义,对于任意一个节点来说,树的高度都等于左子树和右子树中比较大的那个 + 该节点高度1之和。
如果节点为空节点,那么高度就为0,因此,树的高度可以利用递归思想求出:

public int maxDepth(TreeNode root) {
        if(root == null) return 0;
        return Math.max(maxDepth(root.left),maxDepth(root.right)) + 1;
    }

平衡二叉树

那么根据树的高度,由此可以引申出树是否平衡这一概念,也就是平衡二叉树。
平衡二叉树的递归思想:
根据平衡二叉树的定义,一个二叉树每个节点的左右两个子树的高度差的绝对值不超过1。
想要知道每个节点的左右子树的高度差,首先要知道左右子树的高度。
根据树的高度的递归思想,可以轻松得出左右子树的高度,那么进而判断二者之间的绝对值是否大于1,就可以得出答案。

public boolean isBalanced(TreeNode root) {
        int[] isBalanced = {1};
        isBalanced(root,isBalanced);
        return isBalanced[0] > 0;
    }
    //isBalanced用来判断一棵树是否平衡
    private int isBalanced(TreeNode root,int[] isBalanced) {
        if(root == null)return 0;
        int lh = isBalanced(root.left,isBalanced);//分别求出左右子树的高度,
        int rh = isBalanced(root.right,isBalanced);
        if(Math.abs(lh - rh) > 1)//如果高度差大于1,就说明树不平衡
            isBalanced[0] = -1;
        return Math.max(lh,rh) + 1;
    }

二叉树的直径

二叉树的直径是一个新的概念,我们先来看它的定义:

“一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。”
“注意:两结点之间的路径长度是以它们之间边的数目表示。”

这个定义看起来还是很抽象,我们不容易从中发现他的特性,但是通过举例,我们可以很容易将这一概念和树的高度联系起来。

我们来看下面的例子:

    	  1
         / \
        2   3
       / \     
      4   5    

这棵二叉树的直径长度为3,它的长度是路径 [4,2,1,3] 或者 [5,2,1,3],我们根据这两个路径的起始节点和结束节点可以发现其实就是以左叶子节点中的一个到右叶子节点中的一个的距离。
那么回头再看定义中"任意两个结点路径长度中的最大值",就可以发现,树的直径无非就是求树的左子树高度与右子树的高度之和。
根据这一思路,和上面树的高度的递归思想,不难写出如下代码:

public int diameterOfBinaryTree(TreeNode root) {
        int[] res = {0};
        findMaxHeight(root,res);
        return res[0];
    }
    private int findMaxHeight(TreeNode root,int[] res) {
        if(root == null)return 0;
        int lh = findMaxHeight( root.left, res);
        int rh = findMaxHeight( root.right, res);
        res[0] = Math.max(res[0],lh + rh);
        return Math.max(lh,rh) + 1;
    }

树的最小深度

https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/submissions/

树的最小深度就是根节点到叶子节点的最小距离,和树的最大深度正好相反,所以根据文章开头的树的最大深度的代码来讲,只需要将最后的返回条件改为Math.min(left,right)即可。

class Solution {
    public int minDepth(TreeNode root) {
        if(root == null) return 0;
        int left = minDepth(root.left);
        int right = minDepth(root.right);
        //下面这行代码的出现是因为如果有了左右子树其中一个为空时,最短深度就为另外一个不为空的树(根据题意的设定)
        if(left == 0 || right == 0) return left + right + 1;
        return Math.min(left,right) + 1;
    }
}

另外一种递归解法

class Solution {
    public int minDepth(TreeNode root) {
        if(root == null)return 0;
        int[] res = {Integer.MAX_VALUE};
        minDepth(root,res,1);
        return res[0];
    }
    private void minDepth(TreeNode node,int[] res,int cur_Dep) {
        if(node.left == null && node.right == null) {
            res[0] = Math.min(res[0],cur_Dep);
            return;
        }
        if(cur_Dep >= res[0])return;
        if(node.left != null) minDepth(node.left,res,cur_Dep + 1);
        if(node.right != null) minDepth(node.right,res,cur_Dep + 1);        
    }
}

总结

无论是平衡树的概念,还是二叉树的直径的概念。其实核心概念都是树的高度

发布了352 篇原创文章 · 获赞 73 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43777983/article/details/104985557