Prerequisites

Before attempting this problem, you should be comfortable with:

  • Binary Tree Structure - Understanding how nodes connect via left and right children
  • Depth-First Search (DFS) - Traversing trees recursively and returning computed values from subtrees
  • Multi-State Return Values - Tracking multiple pieces of information (increasing/decreasing lengths) at each node
  • Path Combination Logic - Merging paths from left and right subtrees through a common node

1. Brute Force (Time Limit Exceeded)

Intuition

The brute force approach considers every possible path in the tree and checks if it forms a consecutive sequence. For each node, we explore all paths passing through it by examining every possible starting and ending point in its subtrees.

Algorithm

  1. For each node in the tree, consider it as part of a potential consecutive path.
  2. Explore all possible paths that include this node by checking combinations of nodes from left and right subtrees.
  3. For each path, verify if the values form a consecutive sequence (either increasing or decreasing by 1).
  4. Track the maximum length found across all valid consecutive paths.

Time & Space Complexity

  • Time complexity: O(n3)O(n^3)
  • Space complexity: O(n3)O(n^3)

Where nn is the number of nodes in the input tree


2. Single traversal

Intuition

We can find the longest consecutive path in a single traversal by tracking two values at each node: the length of the longest increasing path going down and the length of the longest decreasing path going down. A node can potentially be the turning point where an increasing path from one subtree meets a decreasing path from the other, forming a complete consecutive sequence. By combining these two lengths at each node, we find the longest path passing through that node.

Algorithm

  1. Initialize a global variable to store the maximum path length.
  2. Define a DFS function that returns a pair: [increasing length, decreasing length] starting from the current node.
  3. If the current node is null, return [0, 0].
  4. Start with increasing and decreasing lengths of 1 (just the current node).
  5. For the left child, if it exists and forms a consecutive sequence (value differs by 1), extend the appropriate length.
  6. For the right child, do the same, taking the maximum with any length from the left.
  7. Update the global maximum with (increasing + decreasing - 1), since the current node is counted twice.
  8. Return [increasing, decreasing] for the parent to use.
class Solution:
    def longestConsecutive(self, root: TreeNode) -> int:
                
        def longest_path(root: TreeNode) -> List[int]:
            nonlocal maxval
            
            if not root:
                return [0, 0]
            
            inr = dcr = 1
            if root.left:
                left = longest_path(root.left)
                if (root.val == root.left.val + 1):
                    dcr = left[1] + 1
                elif (root.val == root.left.val - 1):
                    inr = left[0] + 1
            
            if root.right:
                right = longest_path(root.right)
                if (root.val == root.right.val + 1):
                    dcr = max(dcr, right[1] + 1)
                elif (root.val == root.right.val - 1):
                    inr = max(inr, right[0] + 1)
                    
            maxval = max(maxval, dcr + inr - 1)
            return [inr, dcr]
        
        maxval = 0
        longest_path(root)
        return maxval

Time & Space Complexity

  • Time complexity: O(n)O(n)
  • Space complexity: O(n)O(n)

Where nn is the number of nodes in the input tree


Common Pitfalls

Mixing Up Increasing and Decreasing Directions

A node with value parent.val + 1 extends the increasing path from the child's perspective, but it is tracked as dcr (decreasing from root down). The naming can be confusing. Ensure you correctly match which direction each variable tracks.

# If child.val = parent.val - 1, parent extends child's increasing path
# If child.val = parent.val + 1, parent extends child's decreasing path

Forgetting to Subtract 1 When Combining Paths

When combining increasing and decreasing paths through a node, that node is counted in both. The formula is inr + dcr - 1, not inr + dcr.

# Wrong: maxval = max(maxval, inr + dcr)
# Correct: maxval = max(maxval, dcr + inr - 1)

Only Considering One Child for Each Direction

Both left and right children can contribute to either increasing or decreasing paths. You must take the maximum from both children for each direction, not assume left contributes to one and right to the other.