leetcode
leetcode 601 ~ 650
最长同值路径

最长同值路径

难度:

标签:

题目描述

给定一个二叉树的 root ,返回 最长的路径的长度 ,这个路径中的 每个节点具有相同值 。 这条路径可以经过也可以不经过根节点。

两个节点之间的路径长度 由它们之间的边数表示。

 

示例 1:

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

示例 2:

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

 

提示:

  • 树的节点数的范围是 [0, 104] 
  • -1000 <= Node.val <= 1000
  • 树的深度将不超过 1000 

代码结果

运行时间: 140 ms, 内存: 19.5 MB


/*
 * Java Stream 不适用于处理递归和二叉树的问题,所以这里还是使用传统方法。
 * 使用递归方法遍历二叉树。
 * 对于每个节点,计算其左右子树中与当前节点值相同的最长路径。
 * 更新全局变量记录最长路径长度。
 */
 
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}
 
class Solution {
    private int maxLength = 0;
 
    public int longestUnivaluePath(TreeNode root) {
        if (root == null) return 0;
        dfs(root);
        return maxLength;
    }
 
    private int dfs(TreeNode node) {
        if (node == null) return 0;
        int left = dfs(node.left);
        int right = dfs(node.right);
        int leftPath = 0, rightPath = 0;
        if (node.left != null && node.left.val == node.val) {
            leftPath = left + 1;
        }
        if (node.right != null && node.right.val == node.val) {
            rightPath = right + 1;
        }
        maxLength = Math.max(maxLength, leftPath + rightPath);
        return Math.max(leftPath, rightPath);
    }
}
 

解释

方法:

此题解采用深度优先搜索(DFS)来寻找树中的最长同值路径。首先,定义一个全局变量 `ans` 来存储最大路径的长度。对于每一个节点,使用递归函数 `dfs` 来分别计算其左右子树的最长同值路径长度。如果子节点的值与当前节点的值相同,那么该子树对应的最长同值路径就可以与当前节点连起来构成更长的路径。函数返回该节点的单边最长同值路径长度,即左右子树中较长的那个加上当前节点。通过比较和更新全局变量 `ans`,最终 `dfs` 返回后的 `ans` 值即为题目要求的最长同值路径的长度。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
在DFS递归函数中,如果左右子节点的值都与当前节点相同,为什么只更新ans一次而不是两次?
在DFS递归函数中,即使左右子节点的值都与当前节点相同,只更新ans一次是因为我们在寻找的是通过当前节点的最长同值路径,这条路径可以从左子节点经过当前节点到右子节点。如果我们更新两次,可能会错误地计算两条分开的路径长度之和,而实际上我们需要的是一条连续路径。因此,我们在计算ans时,考虑的是一个连续路径的最大长度,而不是两条独立路径的长度总和。
🦆
递归函数中的变量cur_max是如何确保记录了从当前节点出发的单方向最长路径的?
在递归函数中,变量cur_max用于记录从当前节点出发向下延伸的单方向最长同值路径的长度。这是通过计算并比较左右子树返回的同值路径长度来实现的。如果子节点的值与当前节点相同,我们会对该子节点返回的路径长度加一(表示包括当前节点在内的路径),然后更新cur_max。如果有两个子节点都与当前节点值相同,cur_max将记录它们中的最大值,确保cur_max总是表示从当前节点出发的最长单方向路径。
🦆
您提到如果有多个子节点值与当前节点相同,您会选择更新cur_max为最大的那个路径长度,这种选择对结果有什么影响?
如果有多个子节点的值与当前节点相同,选择将cur_max更新为最大的那个路径长度是为了确保我们计算的是最长的单方向路径。这种选择意味着我们在考虑通过当前节点可能形成的最长连续路径时,只考虑了最优的一条路径,这帮助我们避免了重复计算或路径长度的过度估计。这对结果的影响是确保了ans的准确性和最大化,因为ans需要反映树中任何可能的最长同值路径。
🦆
在递归结束后返回ans值,这里是否有需要处理的边界情况,例如空树或只有一个节点的树?
在递归结束后返回ans值时,确实需要考虑边界情况。例如,如果树为空(即根节点为null),则不存在任何路径,ans初始值为0,适用于此情况,直接返回0即可。如果树只有一个节点,由于没有子节点,任何通过该节点的同值路径长度也为0。因此,ans的初始值同样适用,并正确反映了这些边界情况的最长同值路径长度。

相关问题

二叉树中的最大路径和

二叉树中的 路径 被定义为一条节点序列,序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。

路径和 是路径中各节点值的总和。

给你一个二叉树的根节点 root ,返回其 最大路径和

 

示例 1:

输入:root = [1,2,3]
输出:6
解释:最优路径是 2 -> 1 -> 3 ,路径和为 2 + 1 + 3 = 6

示例 2:

输入:root = [-10,9,20,null,null,15,7]
输出:42
解释:最优路径是 15 -> 20 -> 7 ,路径和为 15 + 20 + 7 = 42

 

提示:

  • 树中节点数目范围是 [1, 3 * 104]
  • -1000 <= Node.val <= 1000

统计同值子树

统计同值子树

路径总和 III

给定一个二叉树的根节点 root ,和一个整数 targetSum ,求该二叉树里节点值之和等于 targetSum路径 的数目。

路径 不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。

 

示例 1:

输入:root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8
输出:3
解释:和等于 8 的路径有 3 条,如图所示。

示例 2:

输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
输出:3

 

提示:

  • 二叉树的节点个数的范围是 [0,1000]
  • -109 <= Node.val <= 109 
  • -1000 <= targetSum <= 1000