【每日三题】二叉树最大宽度,寻找重复的子树

100 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第12天,点击查看活动详情 >>


每日三刷,剑指千题

计划简介:

  • 每日三题,以中等题为主,简单题为辅进行搭配。保证质量题1道,数量题3道。
  • 每日早通勤在LeetCode手机端选题,思考思路,没答案的直接看题解。
  • 每日中午进行编码,时间控制在一小时之内。
  • 下班前半小时进行整理总结,并发布到掘金每日更文活动。

说明:

  • 基于以前的刷题基础,本次计划以中等题为主,大部分中等题都可以拆分为多个简单题,所以数量保证3,质量保证一道中等题即可。
  • 刷题顺序按照先刷链表、二叉树、栈、堆、队列等基本数据结构,再刷递归、二分法、排序、双指针等基础算法,最后是动态规划、贪心、回溯、搜索等复杂算法。
  • 刷题过程中整理相似题型,刷题模板。
  • 目前进度 142/1000

[662]二叉树最大宽度

给定一个二叉树,编写一个函数来获取这个树的最大宽度。树的宽度是所有层中的最大宽度。这个二叉树与满二叉树(full binary tree) 结构相同,但一些节点为空。

每一层的宽度被定义为两个端点(该层最左和最右的非空节点,两端点间的null节点也计入长度)之间的长度。

示例 1:

输入: 
​
           1
         /   \
        3     2
       / \     \  
      5   3     9 
​
输出: 4
解释: 最大值出现在树的第 3 层,宽度为 4 (5,3,null,9)。

解析

考虑了半天层序遍历,发现不行,毁在了“两端点间的null节点也计入长度”这个条件。

那猜测应该是DFS,但是怎么写没想起来,看一下解析吧。

忽略了题目的一句话:这个二叉树与满二叉树(full binary tree) 结构相同。顺着满二叉树的思考下去:

主要想法是给每个节点一个 position 值,如果我们走向左子树,那么 position -> position * 2,如果我们走向右子树,那么 position -> positon * 2 + 1。当我们在看同一层深度的位置值 LR 的时候,宽度就是 R - L + 1

Code

class Solution {
        Map<Integer, Integer> left = new HashMap<>();
        int ans = 0;
​
        public int widthOfBinaryTree(TreeNode root) {
            dfs(root, 0, 0);
            return ans;
        }
​
        private void dfs(TreeNode root, int depth, int pos) {
            if (root == null) return;
            // 最左端,不能覆盖
            left.computeIfAbsent(depth, x->pos);
            ans = Math.max(ans, pos - left.get(depth) + 1);
            dfs(root.left, depth + 1, pos * 2);
            dfs(root.right, depth + 1, pos * 2 + 1);
        }
    }

[100]相同的树

给你两棵二叉树的根节点 pq ,编写一个函数来检验这两棵树是否相同。

如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

示例 1:

img

输入:p = [1,2,3], q = [1,2,3]
输出:true

解析

递归遍历,加上条件判断就可以了。

就用前序遍历吧,

Code

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

[652]寻找重复的子树

给定一棵二叉树 root,返回所有重复的子树

对于同一类的重复子树,你只需要返回其中任意一棵的根结点即可。

如果两棵树具有相同的结构相同的结点值,则它们是重复的。

示例 1:

img

输入:root = [1,2,3,4,null,2,4,null,null,4]
输出:[[2,4],[4]]

解析

使用深度优先搜索,其中递归函数返回当前子树的序列化结果。把每个节点开始的子树序列化结果保存在 ma**p 中,然后判断是否存在重复的子树。

对有返回值的递归理解的更深刻了。

Code

class Solution {
        List<TreeNode> ans = new ArrayList<>();
        Map<String, Integer> count = new HashMap();
​
        public List<TreeNode> findDuplicateSubtrees(TreeNode root) {
            dfs(root);
            return ans;
        }
​
        private String dfs(TreeNode root) {
            if (root == null) return "";
            String left = dfs(root.left);
            String right = dfs(root.right);
            String key = root.val + "," + left + "," + right;
            count.put(key, count.getOrDefault(key, 0) + 1);
            if (count.get(key) == 2) {
                ans.add(root);
            }
            return key;
        }
    }

\