1.题目描述:
给定一个二叉树,找到最长的路径,这个路径中的每个节点具有相同值。这条路径可以经过也可以不经过根节点。注意:两个节点之间的路径长度由它们之间的边数表示。
2.解这道题建议先看leetcode543. 二叉树的直径 ,有两种递归解法,自底向上,自顶向下。
自底向上(后序):
不管路径是如何的,将路径想象为从当前节点root左右子节点延长的两条拼凑而成,首先通过递归获得左右子节点的val相同向下延长的最大值,这时需要判断当前root的val值是否与左右子节点的val值相同,若相同则路径可拼凑,否则相当于路径无法拼凑,相应侧贡献的路径长度即为0。用变量记录左右子节点贡献的路径和,其最大值即为题目要求的值。递归的终止条件较为容易,递归的返回值为当前节点与左右子节点的val相同向下延长的最大值,即l和r的最大值,注意是边数,节点数需要+1。代码如下,时间复杂度和空间复杂度都是O(n)。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
private int res = 0;
public int longestUnivaluePath(TreeNode root) {
dfs(root);
return res;
}
private int dfs(TreeNode root){
if (root == null) return 0;
int left = dfs(root.left);
int right = dfs(root.right);
int l = root.left != null && root.left.val == root.val ? left + 1 : 0;
int r = root.right != null && root.right.val == root.val ? right + 1 : 0;
res = Math.max(res, l + r);
return Math.max(l, r);
}
}
自顶向下(前序):
dfs方法依旧为获得val值相同的最大路径长度,此题想用递归直接获得题目的最长同值路径是不行的。longestUnivaluePath方法主要是拼接当前root节点与其左右节点的dfs长度,拼接前需要做出判断,自上而下在遍历每个节点时都会遍历其左右子节点的dfs方法,重复遍历多,时间复杂度较高。
class Solution {
public int longestUnivaluePath(TreeNode root) {
if(root == null) return 0;
int maxLen = 0;
if((root.left != null && root.left.val == root.val) && (root.right != null && root.right.val == root.val)) maxLen = dfs(root.left) + dfs(root.right) + 2;//左右都需要拼接
else if(root.left != null && root.left.val == root.val) maxLen = dfs(root.left) + 1;//只拼接左边
else if(root.right != null && root.right.val == root.val) maxLen = dfs(root.right) + 1;//只拼接右边
int maxLen1 = Math.max(longestUnivaluePath(root.left),longestUnivaluePath(root.right));
return Math.max(maxLen,maxLen1);
}
public int dfs(TreeNode root){
if (root == null) return 0;
int left = dfs(root.left);
int right = dfs(root.right);
int l = root.left != null && root.left.val == root.val ? left + 1 : 0;
int r = root.right != null && root.right.val == root.val ? right + 1 : 0;
return Math.max(l,r);
}
}