这是我参与2022首次更文挑战的第10天,活动详情查看:2022首次更文挑战
题目
687. 最长同值路径
给定一个二叉树的 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
思路
- 树的问题一般可以转换为递归问题,不过我们要区分清楚递归的条件;
- 这道题目求最长的同值路径,那么我们先搞清楚这个路径的定义,简而言之就是经过某个节点的两条边可以组成一条路径;
- 那么我们需要考虑的是,经过哪个节点的边是最长的,所以我们可以用广度优先搜索去遍历每个节点作为根节点的情况,枚举每个节点作为根节点时的最长同值路径,取其中的最大值;
- 然后再求出任意节点最长同值的边长即可,求边长可以转换为递归问题,可以转换为求当前左右两个子节点的最大相等值的递归问题,然后子节点又再次递归去寻找它的更子节点的值即可。
举个例子: 我们求第一个案例的时候
首先枚举第一个节点作为根节点的可能性,然后求它和左右两条子边相等元素长度和的最大值:
左节点的值为4 不相等,不需要继续比较, 右节点的值为5继续递归查找,找出来的总节点为3个,路径等于节点值 - 1也就是等于2
然后继续枚举子节点4和5分别作为路径中根节点的情况继续做比较,4没有相等子节点,找到的结果为0, 第二个5的子节点有一个相等,路径为1, 然后拿这一轮的长度1 和上一轮的长度2做比较,取最大值即可。
一直反复递归到所有节点遍历完成为止即可,然后返回其中的最大值。
实现
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {number}
*/
var longestUnivaluePath = function(root) {
if (!root) return 0;
let queue = [ root ];
let maxPath = 0;
// 深度优先搜索,枚举每个节点作为根节点的可能性
while (queue.length) {
queue = queue.reduce((total, cur) => {
maxPath = Math.max(maxPath, findMaxNode(cur));
cur.left && total.push(cur.left);
cur.right && total.push(cur.right);
return total;
}, []);
}
return maxPath;
};
// 求当前节点作为根节点时的总路径
function findMaxNode(node) {
return getMaxPath(node.left, node.val) + getMaxPath(node.right, node.val);
}
// 求节点的最长路径
function getMaxPath(node, val, count = 0) {
if (!node) return count;
if (node.val === val) {
return Math.max(getMaxPath(node.left, val, count + 1), getMaxPath(node.right, val, count + 1));
} else {
return count;
}
}
看懂了的小伙伴可以点个关注、咱们下道题目见。如无意外以后文章都会以这种形式,有好的建议欢迎评论区留言。