平衡二叉树的判断和优化

1、二叉树的最大高度
  • 分析:二叉树的高度为根节点到最远叶子节点的最长路径上的节点数。
  • 思路:比较根结点的左右子树的最大高度 + 1(到根结点的高度);递到叶子结点那一层把高度依次返回给双亲结点,直到根根结点。
    递推关系:而每一个结点的左子树高度都等于下一个结点的左子树高度+1(右子树那一路递归同理)
    递归出口:递到最左子树为null
	public int maxDepth(TreeNode root) {
        if(root == null) {
            return 0;
        }
        int left = maxDepth(root.left);
        int right = maxDepth(root.right);
        return 1+Math.max(left,right);
    }
2、判断一棵二叉树是否为平衡二叉树

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

  • 分析:
    1、分别求出每个结点的左右子树的高度(如 1)
    2、判断所有结点的左右子树高度差是否满足平衡条件,递归问题。
    递推关系:遍历到每一个结点,求每一个结点的左右子树是否平衡
    终止条件:遍历到结点为 null
  • 思路:
    1、求出当前结点的左右子树的高度
    int leftHeight = getHeight(root.left)
    int rightHeight = getHeight(root.right)
    2、判断当前结点的左右子树的绝对值
    Math.abs(leftHeight,rightHeight)>2 return false
    Math.abs(leftHeight,rightHeight)<2 判断当前结点左右子树是否平衡(左右的高度差)

源代码:

	public boolean isBalanced(TreeNode root) {
         if(root == null) {
             return true;
         }
       int leftHeight = getHeight(root.left);
       int rightHeight = getHeight(root.right);
           if(Math.abs(rightHeight - leftHeight) > 1) {
               return false;
           }
         return isBalanced(root.left) && isBalanced(root.right);
     }

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

这里存在一个效率问题,在判断根结点的时候,左右子树上每一个结点的高度已经求解过,当再求子树是否平衡的时候还需要再求一遍子树每个结点是否平衡

N个结点最坏时间复杂度就是 O(n^2)
在这里插入图片描述
优化:在求解当前结点的高度时,一定会递下去求子树高度,既然每次求当前结点高度都会求到子树的高度,那么有没有办法在求当前结点的时候把子树的平衡性直接判断。

思路:

  • 通过一个参数将高度的判断结果带出来
  • 判断子树平衡性,发现有一例 左/右子树高度差 > 1 的情况时,代表此树不是平衡树,返回-1;
  • 在递的过程求当前结点的高度时,归的时候就会把当前结点以下所有结点情况判断了
  • 一旦发现不是平衡树时,后面高度计算都无意义了,一路直接返回-1,避免后续再计算。
    最差情况是对树做一遍完整DFS,时间复杂度为 O(N)
    递归过程中:
    终止条件:当DFS越过叶子节点时,返回高度0;
    返回值:从底至顶,返回以每个节点root为根节点的子树最大高度 max(left,right) + 1);
 public boolean isBalanced(TreeNode root) {
        return getHeight(root) != -1;
    }

    private int getHeight(TreeNode root) {
        if (root == null) {
        	return 0;
        }
        int leftHeight = getHeight(root.left);
        if(leftHeight == -1) {
        	return -1;
        }
        int rightHeight = getHeight(root.right);
        if(rightHeight == -1) {
        	return -1;
        }
        return Math.abs(leftHeight - rightHeight) < 2 ? 
        Math.max(leftHeight, rightHeight) + 1 : -1;
    }
发布了52 篇原创文章 · 获赞 6 · 访问量 1446

猜你喜欢

转载自blog.csdn.net/qq_40488936/article/details/104692834
今日推荐