↓Skip to main content
  1. LeetCode/

LeetCode 687: Longest Univalue Path

·2 mins· ·
LeetCode Medium Tree Depth-First-Search Binary-Tree Dp-on-Trees
Wei Yi Chung
Author
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
Table of Contents

Meta Data
#

Difficulty: medium First Attempt: 2026-10-24

  • Submissions: Wrong Answer ×2 → Accepted ×2

Approach
#

It is the diameter pattern (LC 543), a DFS return value (Tree Template 1), with the extra rule that values must match:

  • dfs(node) returns the longest downward chain (in edges) from node where every value equals node.val.
  • If the left child has the same value, left = dfs(node.left) + 1, otherwise left = 0. Same for the right.
  • The path bending at node has length left + right and updates the answer; return max(left, right) upward.

My Attempts
#

  1. Passed the node object instead of its value down as the parent value, so node.val == parent was always False and every node returned 0: [2,2] returned 0, the answer is 1.
  2. Passed node.val, but an empty tree returned 0 - 1 = -1; the answer is 0.
  3. Adding the empty-tree check passed.
  4. Rewrote it to count edges directly without passing the parent value; also accepted.

Solution
#

class Solution:
    def longestUnivaluePath(self, root: Optional[TreeNode]) -> int:
        self.longest = 0

        def dfs(node):
            if not node:
                return 0
            left_len = dfs(node.left)
            right_len = dfs(node.right)
            left = left_len + 1 if node.left and node.left.val == node.val else 0
            right = right_len + 1 if node.right and node.right.val == node.val else 0
            self.longest = max(self.longest, left + right)
            return max(left, right)

        dfs(root)
        return self.longest

Complexity
#

Time O(n), space O(h).

Mistakes to Avoid
#

  • Recurse into both children even when their values differ; a longer same-value path may lie below.
  • Count edges. Counting nodes and subtracting 1 gives -1 for an empty tree.
  • Pass node.val, not the node itself.

Interview Explanation
#

This is the diameter pattern: DFS returns the longest downward chain, but a child only extends it when its value equals the node’s, otherwise that side is 0. At each node, left chain plus right chain updates the answer, and the longer side is returned upward. The answer counts edges; time O(n).

Related

LeetCode 1372: Longest ZigZag Path in a Binary Tree
·2 mins
LeetCode Medium Dynamic-Programming Tree Depth-First-Search Binary-Tree Dp-on-Trees
LeetCode 1372 note: each node returns two values, the longest zigzag starting left and starting right; going left extends the left child’s start-right value
LeetCode 124: Binary Tree Maximum Path Sum
·2 mins
LeetCode Hard Dynamic-Programming Tree Depth-First-Search Binary-Tree Dp-on-Trees
LeetCode 124 note: DFS returns the best downward chain and updates the answer with left chain + node + right chain at every node; drop negative chains
LeetCode 515: Find Largest Value in Each Tree Row
·1 min
LeetCode Medium Tree Depth-First-Search Breadth-First-Search Binary-Tree
LeetCode 515 note: BFS level order, taking the maximum of each level; start from -inf
LeetCode 314: Binary Tree Vertical Order Traversal
·2 mins
LeetCode Medium Hash-Table Tree Depth-First-Search Breadth-First-Search Sorting Binary-Tree
LeetCode 314 note: BFS with a column index; BFS is what guarantees top-to-bottom within a column and left-to-right within a row
LeetCode 113: Path Sum II
·2 mins
LeetCode Medium Backtracking Tree Depth-First-Search Binary-Tree
LeetCode 113 note: backtrack with the current path and store a copy at a leaf whose total matches; values can be negative, so no early pruning
LeetCode 117: Populating Next Right Pointers in Each Node II
·2 mins
LeetCode Medium Linked-List Tree Depth-First-Search Breadth-First-Search Binary-Tree
LeetCode 117 note: connect next pointers level by level with BFS; for a non-perfect tree, looking only at the neighbour’s children breaks the chain