当前位置: 面试刷题>> 二叉树的最长连续子序列Ⅱ (经典算法题500道)


题目描述补充

题目:二叉树的最长连续子序列 II

给定一个二叉树,每个节点上都有一个整数值。我们需要找到这棵树中所有可能的连续子序列(不要求是树的子树),并返回这些连续子序列中的最长长度。这里的连续子序列指的是,从根节点开始,可以经过任意节点恰好一次(也可以不经过某些节点),路径上节点的值按顺序排列构成一个递增序列。

注意:与普通的路径问题不同,这里的连续子序列允许“跳跃”某些节点,只要保证路径上的值是递增的即可。

示例

给定二叉树如下:

    3
   / \
  2   4
 /   / \
1   3   5

最长连续子序列为 1 -> 2 -> 3 -> 4 -> 5,因此返回长度为 5

PHP 示例代码

由于 PHP 处理树形结构较为复杂且没有直接的数据结构支持,这里提供一个概念性的思路,实际实现可能需要更多细节处理。

class TreeNode {
    public $val;
    public $left;
    public $right;
    function __construct($val = 0, $left = null, $right = null) {
        $this->val = $val;
        $this->left = $left;
        $this->right = $right;
    }
}

function longestIncreasingSubsequenceII($root) {
    $maxLength = 0;
    dfs($root, PHP_INT_MIN, 1, $maxLength);
    return $maxLength;
}

function dfs($node, $prevVal, $currentLength, &$maxLength) {
    if ($node == null) return;
    
    if ($node->val > $prevVal) {
        $currentLength++;
        $maxLength = max($maxLength, $currentLength);
    } else {
        $currentLength = 1;
    }
    
    $prevVal = $node->val;
    dfs($node->left, $prevVal, $currentLength, $maxLength);
    dfs($node->right, $prevVal, $currentLength, $maxLength);
    
    // 回溯,但由于 PHP 变量传递是按值传递,这里不需要显式回溯 currentLength
}

// 注意:上面的代码只是展示了递归遍历树和比较值的逻辑,并没有直接处理“跳跃”节点的情况。
// 完整处理“跳跃”需要更复杂的状态记录或使用其他数据结构(如动态规划表)。

Python 示例代码

Python 实现通常更直观,但处理“跳跃”仍然需要额外逻辑或数据结构。

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def longestIncreasingSubsequenceII(root):
    def dfs(node, prev, dp):
        if not node:
            return 0
        if node.val > prev:
            # 尝试通过当前节点继续递增
            dp[node.val] = max(dp.get(node.val, 1), dp[prev] + 1)
        # 递归左右子树,不限制必须递增
        dfs(node.left, node.val, dp)
        dfs(node.right, node.val, dp)
        return dp

    # 初始化 dp 为空字典,或使用默认值 {None: 0} 来处理边界情况
    dp = {}
    dfs(root, float('-inf'), dp)
    return max(dp.values(), default=0)

# 注意:这里的实现简化了问题,实际上可能还需要进一步处理来确保“跳跃”的正确性。

JavaScript 示例代码

function TreeNode(val, left, right) {
    this.val = (val===undefined ? 0 : val)
    this.left = (left===undefined ? null : left)
    this.right = (right===undefined ? null : right)
}

function longestIncreasingSubsequenceII(root) {
    let maxLength = 0;
    let dp = new Map();

    function dfs(node, prev) {
        if (!node) return 0;
        let currentLength = 0;
        if (node.val > prev) {
            currentLength = dp.get(prev) + 1;
            dp.set(node.val, currentLength);
            maxLength = Math.max(maxLength, currentLength);
        } else {
            dp.set(node.val, 1);
        }
        dfs(node.left, node.val);
        dfs(node.right, node.val);
    }

    dfs(root, -Infinity);
    return maxLength;
}

// 注意:JavaScript 示例同样简化了问题,实际处理“跳跃”需要更复杂的设计。

码小课:以上代码和思路提供了一个基本的框架,但在处理“跳跃”节点以形成最长连续递增子序列时可能需要进一步的设计和优化。在码小课网站上,你可以找到更多关于树形数据结构、动态规划、递归等算法的深入解析和实战练习,帮助你更好地理解和掌握这类问题。

推荐面试题