【LeetCode题解】二叉树

参考资料

代码随想录

二叉树基础

二叉树遍历

层次遍历

递归解法
BFS解法
例题

102.二叉树的层序遍历
107.二叉树的层次遍历II
199.二叉树的右视图
637.二叉树的层平均值
429.N叉树的前序遍历
515.在每个树行中找最大值
116.填充每个节点的下一个右侧节点指针
117.填充每个节点的下一个右侧节点指针II
104.二叉树的最大深度
111.二叉树的最小深度

116.填充每个节点的下一个右侧节点指针

116.填充每个节点的下一个右侧节点指针
给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:

struct Node {
  int val;
  Node *left;
  Node *right;
  Node *next;
}

填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。

初始状态下,所有 next 指针都被设置为 NULL。

思路一
层次遍历解法

    public Node connect(Node root) {
        if (root == null) {
            return null;
        }
        Queue<Node> queue = new LinkedList<>();
        queue.add(root);
        while (!queue.isEmpty()) {
            int size = queue.size();
            Node pre = null;
            for (int i = 0; i < size; i++) {
                Node poll = queue.poll();
                if (pre != null) {
                    pre.next = poll;
                }
                if (poll.left != null) {
                    queue.add(poll.left);
                }
                if (poll.right != null) {
                    queue.add(poll.right);
                }
                pre = poll;
            }
        }
        return root;
    }

思路二
不适用队列存储,进行层次遍历。
* 连接完全二叉树有两种不同的节点
* 1.直接连接root节点的两个左右子节点
* root.left.next = root.right
* 2.连接两个不同父节点的左右子节点,前提是第i层已经连接好了,即root.next!=null
* root.right.next = root.next.left
* 算法过程:从每一层的最左边的节点start节点开始遍历。start = start.left往前遍历
* 1,逐层遍历,对应root节点,首先连接root节点的左右子节点,然后连接第二种情况
* 2,将root节点往后移动,root=root.next
* 3,往下一层移动start节点,start=start.left,如果start.left==null,说明到了最后一层,停止

    /**
     * 连接完全二叉树有两种不同的节点
     * 1.直接连接root节点的两个左右子节点
     * root.left.next = root.right
     * 2.连接两个不同父节点的左右子节点,前提是第i层已经连接好了,即root.next!=null
     * root.right.next = root.next.left
     * 算法过程:从每一层的最左边的节点start节点开始遍历。start = start.left往前遍历
     * 1,逐层遍历,对应root节点,首先连接root节点的左右子节点,然后连接第二种情况
     * 2,将root节点往后移动,root=root.next
     * 3,往下一层移动start节点,start=start.left,如果start.left==null,说明到了最后一层,停止遍历
     * @param root
     * @return
     */
    public Node connect2(Node root) {
        if (root == null) {
            return null;
        }
        Node start = root;
        while (start.left != null) {
            Node cur = start;
            while (cur != null) {
                cur.left.next = cur.right;// 完全二叉树,一定有left节点跟right节点
                if (cur.next != null) {
                    cur.right.next = cur.next.left;
                }
                cur = cur.next;
            }
            start = start.left;
        }
        return root;
    }
117.填充每个节点的下一个右侧节点指针II

思路一
层次遍历解法。

思路二
常数空间复杂度,不需要额外的空间进行层次遍历。
中心思想是:
每一层都可以看做是一条链表,在遍历上一层的过程中,对下一层的节点建立一条链表。

    public Node connect(Node root) {
        if (root == null)
            return root;
        //cur我们可以把它看做是每一层的链表
        Node cur = root;
        while (cur != null) {
            //遍历当前层的时候,为了方便操作在下一
            //层前面添加一个哑结点(注意这里是访问
            //当前层的节点,然后把下一层的节点串起来,其实就是以下一层为基础建立一个链表
            Node dummy = new Node(0);
            //pre表示访下一层节点的前一个节点
            Node pre = dummy;
            //然后开始遍历当前层的链表
            while (cur != null) {
                if (cur.left != null) {
                    //如果当前节点的左子节点不为空,就让pre节点
                    //的next指向他,也就是把它串起来
                    pre.next = cur.left;
                    //然后再更新pre
                    pre = pre.next;
                }
                //同理参照左子树
                if (cur.right != null) {
                    pre.next = cur.right;
                    pre = pre.next;
                }
                //继续访问这一层的下一个节点
                cur = cur.next;
            }
            //把下一层串联成一个链表之后,让他赋值给cur,
            //后续继续循环,直到cur为空为止,指向下一层的第一个节点
            cur = dummy.next;
        }
        return root;
    }
104. 二叉树的最大深度

给定一个二叉树,找出其最大深度。

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

说明: 叶子节点是指没有子节点的节点。

示例:
给定二叉树 [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

思路一
层次遍历

思路二
深度优先搜索。更高效

    public int maxDepth(TreeNode root) {
        if (root == null) {
            return 0;
        } else {
            int leftHeight = maxDepth(root.left);
            int rightHeight = maxDepth(root.right);
            return Math.max(leftHeight, rightHeight) + 1;
        }
    }
111. 二叉树的最小深度

111. 二叉树的最小深度

给定一个二叉树,找出其最小深度。

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

说明:叶子节点是指没有子节点的节点。

思路一
层次遍历。


    public int minDepth2(TreeNode root) {
       if (root == null) {
           return 0;
       }
       int min =1;// 细节
       Queue<TreeNode> queue = new LinkedList<>();
       queue.add(root);
       while (!queue.isEmpty()) {
           int size = queue.size();
           for (int i = 0; i < size; i++) {
               TreeNode poll = queue.poll();
               if (poll.left == null && poll.right == null) { // 找到叶子节点
                   return min;
               }
               if (poll.left != null) {
                   queue.add(poll.left);
               }
               if (poll.right != null) {
                   queue.add(poll.right);
               }
           }
           min++;
       }
       return min;
   }

思路二

深度优先搜索

    public int minDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        if (root.left == null && root.right == null) {
            return 1;
        }
        int min = Integer.MAX_VALUE;
        if (root.left != null) { // 细节,不为null才去继续求,区别于最大深度
            min = Math.min(min, minDepth(root.left));
        }
        if (root.right != null) {
            min = Math.min(min, minDepth(root.right));
        }
        return min + 1;
    }

二叉树的深度

平衡二叉树

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

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

最小深度

最大深度

完全二叉树的节点数

力扣题目链接

给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。

完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。

思路

  1. 先计算出左右子树的层数left和right
  2. 如果left==right,利用完全二叉树的性质,left节点一定是满二叉树
  3. 如果left!=right,利用完全二叉树的性质,right节点一定是满二叉树

代码

    class Solution {
        public int countNodes(TreeNode root) {
            if (root == null) {
                return 0;
            }
            int left = countLevel(root.left);// 左子树的层数
            int right = countLevel(root.right); // 右子树的层数
            if (left == right) { //
                return countNodes(root.right) + (1 << left); // 左子树是满二叉树
            } else {
                return countNodes(root.left) + (1 << right); // 右子树是满二叉树
            }
        }

        /**
         * 计算层数
         * @param root
         * @return
         */
        private int countLevel(TreeNode root) {
            int level = 0;
            while (root != null) {
                level++;
                root = root.left;
            }
            return level;
        }
    }

二叉树比较与变换

对称二叉树

    class Solution {
        public boolean isSymmetric(TreeNode root) {
            if (root == null) {
                return true;
            }
            return isSymmetric(root.left, root.right);
        }

        /**
         * 两颗树是否是对称的
         * @param left
         * @param right
         * @return
         */
        private boolean isSymmetric(TreeNode left, TreeNode right) {
            if (left == null && right == null) {
                return true;
            }
            if (left == null || right == null) {
                return false;
            }
            return left.val == right.val && isSymmetric(left.right, right.left) && isSymmetric(left.left, right.right);
        }
    }

反转二叉树

相同二叉树

    class Solution {
        public boolean compare(TreeNode tree1, TreeNode tree2) {
            if (tree1 == null && tree2 == null) return true;
            if (tree1 == null || tree2 == null) return false;
            if (tree1.val != tree2.val) return false;
            // 此时就是:左右节点都不为空,且数值相同的情况
            // 此时才做递归,做下一层的判断
            boolean compareLeft = compare(tree1.left, tree2.left);       // 左子树:左、 右子树:左
            boolean compareRight = compare(tree1.right, tree2.right);    // 左子树:右、 右子树:右
            return compareLeft && compareRight;

        }
        boolean isSameTree(TreeNode p, TreeNode q) {
            return compare(p, q);
        }
    }

二叉树的路径

二叉树的所有路径

二叉树的所有路径

给定一个二叉树,返回所有从根节点到叶子节点的路径。
说明: 叶子节点是指没有子节点的节点。

代码

    public List<String> binaryTreePaths(TreeNode root) {
        if (root == null) {
            return Collections.EMPTY_LIST;
        }
        List<String> result = new ArrayList<>();
        List<TreeNode> path = new ArrayList<>();
        backTracking(root, result, path);
        return result;
    }

    private void backTracking(TreeNode root, List<String> result, List<TreeNode> path) {
        if (root == null) {
            return;
        }
        path.add(root);
        if (root.left == null && root.right == null) {
            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 0; i < path.size(); i++) {
                stringBuilder.append(path.get(i).val);
                if (i != path.size() - 1) {
                    stringBuilder.append("->");
                }
            }
            result.add(stringBuilder.toString());
        }
        backTracking(root.left, result, path);
        backTracking(root.right, result, path);
        path.remove(path.size() - 1);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值