[LeetCode] 687. Longest Univalue Path

本文探讨了二叉树中寻找最长相同值路径的问题,提出了三种解决方案:朴素递归、带备忘录的递归及更简洁的实现。通过实例演示了如何计算包含或不包含当前节点的最长路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Given a binary tree, find the length of the longest path where each node in the path has the same value. This path may or may not pass through the root.

Note: The length of path between two nodes is represented by the number of edges between them.

Example 1:

Input:

              5
             / \
            4   5
           / \   \
          1   1   5

 

Output:

2

 

Example 2:

Input:

              1
             / \
            4   5
           / \   \
          4   4   5

 

Output:

2

 

Note: The given binary tree has not more than 10000 nodes. The height of the tree is not more than 1000.

 

Similar with Binary Tree Max Path Sum,  for a given node t, the longest univalue path of this subtree whose root is t, the longest univalue path either includes t or not include t. If not including t, then the answer is either the longest univalue path of t's left subtree or right subtree. If including t, then the answer will be the sum between the left subtree longest straight path and the right subtree longest straight path. 

 

Solution 1. Naive Recursion.

 1 class Solution {
 2     public int longestUnivaluePath(TreeNode root) {
 3         if(root == null) {
 4             return 0;
 5         }
 6         int leftLongestPath = longestUnivaluePath(root.left);
 7         int rightLongestPath = longestUnivaluePath(root.right);
 8         int longestPathWithoutCurrentNode = Math.max(leftLongestPath, rightLongestPath);
 9         int leftLongestSinglePath = longestSinglePath(root.left);
10         int rightLongestSinglePath = longestSinglePath(root.right);
11         int longestPathWithCurrentNode = 0;
12         if(root.left != null && root.left.val == root.val) {
13             longestPathWithCurrentNode += (leftLongestSinglePath + 1);
14         }
15         if(root.right != null && root.right.val == root.val) {
16             longestPathWithCurrentNode += (rightLongestSinglePath + 1);
17         }      
18         return Math.max(longestPathWithoutCurrentNode, longestPathWithCurrentNode);
19     }
20     private int longestSinglePath(TreeNode node) {
21         if(node == null) {
22             return 0;
23         }
24         int leftLongestSinglePath = node.left != null && node.left.val == node.val ? longestSinglePath(node.left) + 1 : 0;
25         int rightLongestSinglePath = node.right != null && node.right.val == node.val ? longestSinglePath(node.right) + 1 : 0;
26         return Math.max(leftLongestSinglePath, rightLongestSinglePath);
27     }
28 }

 

The problem with solution is that when computing longest sing path for a subtree, it does not memoize any smaller subtrees' computation result. It always recursively exhaust all nodes of a subtree to get the longest single path. Since each longestSingePath call recursively calls another two longestSinglePath, the runtime for this method alone is O(2^h), where h is the height of a given subtree. 

 

Solution 2. Recursion with memoization when computing longest single path for a subtree.

 1 class Solution {
 2     class ResultType {
 3         int singlePath;
 4         int maxPath;
 5         Integer val;
 6         ResultType(int sp, int mp, Integer v) {
 7             this.singlePath = sp;
 8             this.maxPath = mp;
 9             this.val = v;
10         }
11     }
12     public int longestUnivaluePath(TreeNode root) {
13         ResultType result = helper(root);
14         return result.maxPath;
15     }
16     private ResultType helper(TreeNode node) {
17         if(node == null) {
18             return new ResultType(0, 0, null);
19         }
20         ResultType left = helper(node.left);
21         ResultType right = helper(node.right);
22         int singlePath = 0;
23         if(left.val != null && left.val == node.val) {
24             singlePath = left.singlePath + 1;
25         }
26         if(right.val != null && right.val == node.val) {
27             singlePath = Math.max(singlePath, right.singlePath + 1);
28         }
29         int maxPathWithoutCurrentNode = Math.max(left.maxPath, right.maxPath);
30         int maxPathWithCurrentNode = 0;
31         if(left.val != null && left.val == node.val) {
32             maxPathWithCurrentNode += (left.singlePath + 1);
33         }
34         if(right.val != null && right.val == node.val) {
35             maxPathWithCurrentNode += (right.singlePath + 1);
36         }
37         int maxPath = Math.max(maxPathWithoutCurrentNode, maxPathWithCurrentNode);
38         return new ResultType(singlePath, maxPath, node.val);
39     }
40 }

 

Solution 3. A cleaner implementation with the same memoization idea

 1 class Solution {
 2     int ans = 0;
 3     public int longestUnivaluePath(TreeNode root) {
 4         helper(root);
 5         return ans;
 6     }
 7     private int helper(TreeNode node) {
 8         if(node == null) {
 9             return 0;
10         }
11         int leftMaxPath = helper(node.left);
12         int rightMaxPath = helper(node.right);
13         int leftMaxPathWithCurrentNode = node.left != null && node.left.val == node.val ? leftMaxPath + 1 : 0;
14         int rightMaxPathWithCurrentNode = node.right != null && node.right.val == node.val ? rightMaxPath + 1 : 0;
15         ans = Math.max(ans, leftMaxPathWithCurrentNode + rightMaxPathWithCurrentNode);
16         return Math.max(leftMaxPathWithCurrentNode, rightMaxPathWithCurrentNode);
17     }
18 }

 

转载于:https://www.cnblogs.com/lz87/p/10222911.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值