题目来源:🔒LeetCode 298. 二叉树最长连续序列
问题抽象: 给定一个二叉树的根节点 root
,要求计算树中最长的 连续递增序列路径 的长度(路径必须沿父子连接方向向下),满足以下核心需求:
-
序列规则定义:
- 严格递增:路径中每个节点的值必须 严格等于前一节点值加 1(如
1→2→3
有效,1→3
无效); - 向下单向:路径方向必须 从父节点指向子节点(不可向上或跨分支);
- 任意起止:序列可起始于任意节点,终止于任意节点(无需从根开始或到叶子结束)。
- 严格递增:路径中每个节点的值必须 严格等于前一节点值加 1(如
-
计算目标:
- 返回最长连续递增序列的长度(整数
≥1
); - 结果需覆盖树的所有可能路径(全局最优)。
- 返回最长连续递增序列的长度(整数
-
输入约束:
- 节点数
0 ≤ n ≤ 3×10^4
,节点值-10^4 ≤ val ≤ 10^4
; - 时间复杂度 O(n)(需遍历所有节点一次);
- 空间复杂度 O(h)(递归栈深度,
h
为树高)。
- 节点数
-
边界处理:
- 空树:输出
0
; - 单节点树:输出
1
(自身构成序列); - 非连续树:如父节点
3
的子节点为1
和2
,最长序列为1
(无连续递增); - 负值序列:如
-3→-2→-1
长度为3
; - 分支竞争:如根
1
的左右子分别为2
和3
,则路径1→2
和1→3
均有效(长度2
)。
- 空树:输出
输入:二叉树根节点 root
(节点定义:TreeNode
含 val
, left
, right
)
输出:最长连续递增序列长度(整数)。
解题思路
核心目标:在二叉树中寻找一条从父节点到子节点的路径,使得路径上每个节点的值严格递增 1(即连续序列),并返回最长路径的长度。
算法选择:深度优先搜索(DFS)
- 自顶向下递归:从根节点开始向下遍历,记录当前连续序列的长度。
- 状态传递:
- 若当前节点值 = 父节点值 + 1,则当前连续序列长度
len + 1
; - 否则重置当前连续序列长度为
1
(以当前节点为新起点)。
- 若当前节点值 = 父节点值 + 1,则当前连续序列长度
- 更新全局最大值:在每次递归中更新全局最长序列长度
maxLen
。
时间复杂度:O(n)
,每个节点仅访问一次。 空间复杂度:O(h)
,递归栈深度取决于树的高度 h
(最坏情况为链状树 O(n)
)。
代码实现(Java版)🔥点击下载源码
class Solution {
private int maxLen = 1; // 全局最大值,至少为1(单节点路径)
public int longestConsecutive(TreeNode root) {
dfs(root, null, 1); // 初始父节点为null,当前长度=1
return maxLen;
}
private void dfs(TreeNode node, TreeNode parent, int len) {
if (node == null) return;
// 若父节点非空且当前节点值 = 父节点值 + 1,则连续序列延长;否则重置为1
if (parent != null && node.val == parent.val + 1) {
len++;
maxLen = Math.max(maxLen, len); // 更新全局最大值
} else {
len = 1; // 不满足连续条件,重置长度
}
// 递归左右子树,传入当前节点作为父节点
dfs(node.left, node, len);
dfs(node.right, node, len);
}
}
代码说明
- 初始化:
maxLen
初始化为1
(最小合法路径为单个节点)。
- DFS 递归函数:
- 参数:当前节点
node
、父节点parent
、当前连续序列长度len
。 - 终止条件:节点为空时返回。
- 连续性判断:
- 若当前节点是父节点的连续后继(
node.val == parent.val + 1
),则len++
; - 否则重置
len = 1
(以当前节点为新序列起点)。
- 若当前节点是父节点的连续后继(
- 更新全局最大值:每次递归后更新
maxLen = max(maxLen, len)
。
- 参数:当前节点
- 遍历子树:对左右子树递归调用
dfs
,将当前节点作为父节点传递。