随想录训练营Day16 | 104. 二叉树的最大深度, 559.N 叉树的最大深度,101.二叉树的最小深度, 110.平衡二叉树

95 阅读3分钟

随想录训练营Day16 | 104. 二叉树的最大深度, 559.N 叉树的最大深度,101.二叉树的最小深度, 110.平衡二叉树

标签: LeetCode闯关记


104. 二叉树的最大深度

  • 递归法
class Solution {
    public int maxDepth(TreeNode root) {
        //求最大深度就是求根节点的高度,采用后序遍历,将得到的左右子树的高度的最大值返回给父节点,父节点的高度就是该最大值+1;
        //终止条件
        if(root == null){
            return 0;
        }
        //每一次递归的操作
        int leftDepth = maxDepth(root.left);//左
        int rightDepth = maxDepth(root.right);//右
        return Math.max(leftDepth,rightDepth) + 1;//关键:中 + 1 返回父节点的高度
    }
}
  • 迭代法
class Solution {
    public int maxDepth(TreeNode root) {
        //层序遍历,用栈来实现
        Deque<TreeNode> deque = new LinkedList<>();
        int depth = 0;
        if (root == null) {
            return depth;
        }
        deque.add(root);
        while (!deque.isEmpty()) {
            depth++;
            int len = deque.size();
            while (len > 0) {
                TreeNode node = deque.pop();
                if (node.left != null) {
                    deque.offer(node.left);
                }
                if (node.right != null) {
                    deque.offer(node.right);
                }
                len--;
            }
        }
        return depth;
    }
}

559.N 叉树的最大深度

  • 层序遍历
class Solution {
    public int maxDepth(Node root) {
    //层序遍历
    Deque<Node> deque = new LinkedList<>();
    int depth = 0;
    if(root == null){
    return depth;
}
deque.add(root);
while (! deque.isEmpty()){
    int len = deque.size();
    while ((len-- > 0)){
        Node node = deque.pop();
        for (Node child : node.children) {
            if(child != null){
                deque.add(child);
            }
        }
    }
    depth++;
}
return depth;
}
}
  • 迭代法+层序遍历
class Solution {
    public int maxDepth(Node root) {
        //后序遍历
        if(root == null){
            return 0;
        }
        int depth = 0;

        //Q:这里是否需要if判断 if (root.children != null)
        for (Node child : root.children) {
                depth = Math.max(depth, maxDepth(child));
        }//类比二叉树先遍历的:左右
        return depth + 1;//类比二叉树遍历的: 中 //一定要+ 1 :理解为什么 因为子节点访问到null之后会返回0,那么返回其父节点的高度就为 0+1;
    }
}

101.二叉树的最小深度

  • 迭代法:层序遍历
class Solution {
    //迭代法
    public int minDepth(TreeNode root) {

        Deque<TreeNode> deque = new LinkedList<>();
        if(root == null){return 0;}
        deque.add(root);
        int depth = 0;//用以记录深度
        while (!deque.isEmpty()){
            int len = deque.size();
            depth++;
            for (int i = 0; i < len; i++) {
                TreeNode node = deque.pop();
                if(node.left != null){
                    deque.add(node.left);
                }
                if(node.right != null){
                    deque.add(node.right);
                }
                if(node.left == null && node.right == null){//关键
                    return depth;
                }
            }
        }
        return depth;
    }
}
  • 递归法 + 后序遍历
class Solution {
    //递归法,后序遍历
    public int minDepth(TreeNode root) {
        if(root == null){
            return 0;
        }
        int leftMinDepth = minDepth(root.left);
        int rightMinDepth = minDepth(root.right);
        if (root.left == null){ //关键判断
            return rightMinDepth + 1;
        }
        if(root.right == null){//关键判断
            return leftMinDepth + 1;
        }
        // if (root.left != null && root.right != null)
        return Math.min(leftMinDepth,rightMinDepth) + 1;
    }
}

222.完全二叉树的节点个数

当作普通二叉树来做

  • 递归法
class Solution {
    //按照普通二叉树来做, 递归法
    public int countNodes(TreeNode root) {
        if(root == null){
            return 0;
        }
        int leftCount = countNodes(root.left);
        int rightCount = countNodes(root.right);
        return (leftCount + rightCount + 1);
    }
}
  • 迭代法
class Solution {
    //按照普通二叉树来做, 迭代法
    public int countNodes(TreeNode root) {
        Deque<TreeNode> deque = new LinkedList<>();
        if(root == null){return 0;}
        deque.add(root);
        int count = 0;//用以记录节点数
        while (!deque.isEmpty()){
            int len = deque.size();
            for (int i = 0; i < len; i++) {
                TreeNode node = deque.pop();
                count++;
                if(node.left != null){
                    deque.add(node.left);
                }
                if(node.right != null){
                    deque.add(node.right);
                }
            }
        }
        return count;
    }
}
  • 根据完全二叉树特性的递归法
  • 根据完全二叉树的特性
  • 思路: 利用递归找完全二叉树中的满二叉树,注意,不会陷入死循环,因为叶子节点必定是满二叉树;
  • 理解这种方法的好处: 可以不遍历满二叉树的内侧节点,在数据量很大的情况下,效果很明显;
  • 此方法注意: 1. 终止条件有两个,①root == null; ②找到满二叉树;
  • tips: 理解递归,还是就分成三种理解,不用整理理解,很容易晕;
  • 这个方法的效果的话,我认为,应该是①如果不是满二叉树,肯定遇到终止条件1,root == null, 所以自下而上记录节点数,就像遍历普通二叉树一样;②if满足终止条件2,说明找到满二叉树,则利用其特性2^k - 1, 算出节点,而不需要遍历整个满二叉树,即不需要触发终止条件1(root == null).
class Solution {
    public int countNodes(TreeNode root) {
        //终止条件1
        if(root == null){
            return 0;
        }
        TreeNode left = root.left;
        TreeNode right = root.right;
        int leftlen = 0; //细节: 理解初始为0的原因 ---联系满二叉树的节点数:2^k - 1 以及位运算: int result = 2 << 2; // 等价于 2的3次方
        int rightlen = 0;
        while(left != null){//关键:求左子树的深度   //Q:有没有递归的动画演示? 
            left = left.left;
            leftlen++;
        }
        while(right != null){//求右子树的深度
            right = right.right;
            rightlen++;
        }
        if(rightlen == leftlen){ //终止条件2
            return  (2 << rightlen) - 1;// 注意(2<<1) 相当于2^2,所以leftDepth初始为0; `<<`表示在二进制中,左移并补0;
        }
        //后序遍历,左右中
        int leftCount = countNodes(root.left);//左
        int rightCount = countNodes(root.right);//右
        return leftCount + rightCount + 1;//中
    }
}

110.平衡二叉树

class Solution {
    //思路: 高度平衡-高度-后续遍历-左右中 关键点:比较左右子树的高度,若发现有子树的高度差大于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);//左
        //添加判断条件,如果左子树已经确定不是平衡二叉树了,直接终止
        // Q:不是很懂为什么还要判断,不是"if(Math.abs(leftHeight - rightHeight) > 1 ){return -1;}"就能够判断不是平衡二叉树,并且终止比较了吗?
        if(leftHeight == -1){
            return -1;
        }

        int rightHeight = getHeight(root.right);//右
        //添加判断条件,如果右子树已经确定不是平衡二叉树了,直接终止
        if(rightHeight == -1){
            return -1;
        }

        // 左右子树高度差大于1,return -1表示已经不是平衡树了
        if(Math.abs(leftHeight - rightHeight) > 1 ){
            return -1;
        }else{//基于左子树的高度和右子树的高度 并加上当前父节点 返回当前父节点的高度
            return Math.max(leftHeight,rightHeight) + 1;
        }
    }
}

发问: Q:不是很懂为什么还要判断,不是"if(Math.abs(leftHeight - rightHeight) > 1 ){return -1;}"就能够判断不是平衡二叉树,并且终止比较了吗?