【算法练习】二叉树专题

王传学

关注

阅读 42

2022-03-12

100、相同的树(简单)

在这里插入图片描述

class Solution {
    public boolean isSameTree(TreeNode p, TreeNode q) {
        if (p == null && q == null) return true;
        if (p == null || q == null || p.val != q.val) return false;
        return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
    }
}

107、二叉树的层序遍历Ⅱ(中等)

在这里插入图片描述
在正常层序遍历的基础上,把后面的结果插在前面即可。

class Solution {
    public List<List<Integer>> levelOrderBottom(TreeNode root) {
        List<List<Integer>> ans = new LinkedList<>();
        if (root == null) return ans;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            int sz = queue.size();
            List<Integer> tmp = new LinkedList<>();
            for (int i = 0; i < sz; i++) {
                TreeNode t = queue.poll();
                tmp.add(t.val);
                if (t.left != null) queue.offer(t.left);
                if (t.right != null) queue.offer(t.right);
            }
            ans.add(0, tmp);
        }
        return ans;
    }
}

※111、二叉树的最小深度(简单)

在这里插入图片描述
还是想了一会,主要是左右节点为空的特判,需要注意一下。反正这种问题从宏观上去想,再加上base case。

class Solution {
    public int minDepth(TreeNode root) {
        if (root == null) return 0;
        // 到达叶子节点,算一个
        if (root.left == null && root.right == null) {
            return 1;   
        }
        // 左节点为空,只能去看右节点,当然也要算上自己
        if (root.left == null) return 1 + minDepth(root.right);
        // 右节点为空,只能去看左节点
        if (root.right == null) return 1 + minDepth(root.left);
        int leftMin = minDepth(root.left);
        int rightMin = minDepth(root.right);
        // 根节点自己+1
        return Math.min(leftMin, rightMin) + 1;   
    }
}

117、填充每个节点的下一个右侧节点指针 II(中等)

在这里插入图片描述
在这里插入图片描述
本题和填充每个节点的下一个右侧节点指针区别在于本题不再是完全二叉树,需要考虑的因素较多,用递归就不太适合了,更适合使用层序遍历进行。

下面是116题目的代码,比较简单,就是拆分成两个子树进行连接

class Solution {
    public Node connect(Node root) {
        if (root == null) return root;
        // 初始状态下,所有的next指针都设置为NULL,所以根节点不用管
        setNext(root.left, root.right);
        return root;
    }
    void setNext(Node root1, Node root2) {
        if (root1 == null) {
            // 完美二叉树,没有左子节点一定没有右子节点
            // 没有右子节点,一定没有左子节点
            return;
        }
        // 左右连接起来
        root1.next = root2;
        setNext(root1.left, root1.right);
        setNext(root1.right, root2.left);
        setNext(root2.left, root2.right);
    }
}

上面的代码没有用队列,所以空间复杂度为O(1),下面给出使用队列的层序遍历解法(空间复杂度为O(n)):

class Solution {
    public Node connect(Node root) {
        if (root == null) return root;
        Queue<Node> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            int sz = queue.size();
            for (int i = 0; i < sz; i++) {
                Node cur = queue.poll();
                // 拿出来的节点一定会和当前队列中的头结点相连
                // 因为我们是按照左、右子结点入队的
                if (i < sz - 1) {
                    // 最后一个结点就不能再连接了
                    cur.next = queue.peek();
                }
                if (cur.left != null) {
                    queue.offer(cur.left);
                }
                if (cur.right != null) {
                    queue.offer(cur.right);
                }
            }
        }
        return root;
    }
}

完全二叉树简化了做题难度,回到117,普通的二叉树该怎么办?

用层序遍历,和上面一摸一样的代码…

class Solution {
    public Node connect(Node root) {
        if (root == null) return root;
        Queue<Node> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            int sz = queue.size();
            for (int i = 0; i < sz; i++) {
                Node cur = queue.poll();
                if (i < sz - 1) {
                    // 这一层最后一个点就不用连了
                    cur.next = queue.peek();
                }
                if (cur.left != null) queue.offer(cur.left);
                if (cur.right != null) queue.offer(cur.right);
            }
        }
        return root;
    }
}

有空继续刷!

精彩评论(0)

0 0 举报