LeetCode 872. 叶子相似的树
题目描述



题意分析
把一棵树的所有叶子按从左到右的顺序取出它们的值,得到叶值序列。判断两棵树的这个序列是否完全相同:长度、每个位置的值以及重复次数都必须一致。
只比较叶子,内部节点的值和树的整体形状不需要相同。叶子必须同时没有左右孩子,只有一侧为空的节点仍是内部节点。题目保证两棵树都非空。
解法:按从左到右顺序收集叶值
核心思路
[!blue]
分别遍历两棵树,只在叶子处记录值。要得到从左到右的顺序,每个节点都先完整遍历左子树,再完整遍历右子树:左子树中的所有叶子都位于右子树叶子的左边,递归内部继续遵守相同规则,就能得到全树的叶值顺序。
如果当前节点是叶子,将它的值追加到列表后返回;否则只递归存在的孩子。内部节点不写入列表,所以即使两棵树的根值、层数或分叉形状不同,也不会干扰真正要比较的序列。
代码用左右孩子引用是否相同判断叶子。正规二叉树不会让两个孩子共享同一个非空节点,因此引用相同只可能是两边都为空;这个比较并不是比较左右孩子的数值。根由题目保证非空,递归调用前又检查孩子存在,所以函数内部无需再处理空参数。
收集完成后比较两个序列。Java 的
List.equals同时检查长度及对应值,Go 则先检查长度,再逐位置比较。长度不同或者任一位置不同,就不满足叶相似;只有完整一致才返回真。每个节点都只访问一次,比较的是有顺序的列表而非集合,因而不会丢掉同值叶子多次出现的信息。
解题步骤
- 为两棵树分别创建叶值列表。
- 从根开始 DFS,遇到叶子就追加当前值并返回。
- 非叶子先处理非空左孩子,再处理非空右孩子。
- 比较两个叶值列表是否长度相同且逐项相同,返回结果。
代码实现
class Solution {
public boolean leafSimilar(TreeNode root1, TreeNode root2) {
List<Integer> l1 = new ArrayList<>();
List<Integer> l2 = new ArrayList<>();
dfs(root1, l1);
dfs(root2, l2);
return l1.equals(l2);
}
private void dfs(TreeNode root, List<Integer> nums) {
if (root.left == root.right) {
nums.add(root.val);
return;
}
if (root.left != null) {
dfs(root.left, nums);
}
if (root.right != null) {
dfs(root.right, nums);
}
}
}
func leafSimilar(root1 *TreeNode, root2 *TreeNode) bool {
l1, l2 := []int{}, []int{}
var dfs func(*TreeNode, *[]int)
dfs = func(root *TreeNode, nums *[]int) {
if root.Left == root.Right {
*nums = append(*nums, root.Val)
return
}
if root.Left != nil {
dfs(root.Left, nums)
}
if root.Right != nil {
dfs(root.Right, nums)
}
}
dfs(root1, &l1)
dfs(root2, &l2)
if len(l1) != len(l2) {
return false
}
for i, v := range l1 {
if v != l2[i] {
return false
}
}
return true
}
复杂度分析
- 时间复杂度:$O(n_1 + n_2)$,两棵树各遍历一次,列表比较最多再检查所有叶子。
- 空间复杂度:$O(L + \max(h_1, h_2))$,
L为两树叶子总数,h_1、h_2为树高。两个结果列表需要同时保留,两次递归则先后执行,只计较大的栈深度。
关键点总结
[!green]
- 先左后右保证叶值的空间顺序,只有真正的叶子进入结果。
- 树的内部结构可以不同,比较单位是叶值序列。
- 列表保留顺序与次数,才能表达叶相似的完整条件。
易错点总结
[!yellow]
- 只比较叶子集合、数量或总和,会漏掉顺序与重复次数上的差异。
- 只有一侧孩子为空就判为叶子,会把内部节点值误加入序列。
- 改为先右后左遍历其中一棵树,会让两份列表采用不同顺序。
- 将
left == right误读为孩子值相等,可能把两个同值非空孩子的父节点当成叶子。- 比较整棵树的形状或全部节点值,会把本来叶相似的不同结构错误排除。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 100. 相同的树 | 简单 | 原题要求所有节点及结构相同,本题只比较从左到右的叶值序列。 |
| 94. 二叉树的中序遍历 | 简单 | 都依靠先处理左侧来稳定输出顺序,本题只输出叶子而不是所有中序节点。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!