Longest Univalue Path

Updated on 06 June, 2025
Longest Univalue Path header image

Problem Statement

Given the root of a binary tree, the challenge is to ascertain the maximal extent of a path where every node shares the same value. This path might either pass through or circumvent the root of the tree. To clarify, the 'length of the path' in this context refers to the count of edges that connect sequential nodes along the path. The objective is not just to find a path but to find the longest one where the same numerical value is repeated throughout consecutive nodes in the tree.

Examples

Example 1

Input:

root = [5,4,5,1,1,null,5]

Output:

2

Explanation:

The longest path of same values consists of two nodes with value 5 connected through the right subtree: 5 -> 5.

Example 2

Input:

root = [1,4,5,4,4,null,5]

Output:

2

Explanation:

The longest path of same values consists of two nodes with value 4 connected through the left subtree: 4 -> 4.

Constraints

  • The number of nodes in the tree is in the range [0, 10^4].
  • -1000 <= Node.val <= 1000
  • The depth of the tree will not exceed 1000.

Approach and Intuition

The task involves tracing the longest unbroken sequence where all nodes hold the same value. This scenario requires a continuous comparison of node values during traversal and simultaneous tracking of sequence length.

  1. Recursive Depth-First Search (DFS):

    • Use DFS to explore every node in the tree.
    • For each node, recursively determine the longest univalue path in the left and right subtrees.
  2. Path Extension Logic:

    • If the child node's value equals the current node's value, the path can be extended.
    • Track the length of the left and right univalue paths separately.
  3. Calculate and Update Global Maximum:

    • At each node, compute the combined path length if both left and right univalue paths extend from it.
    • Update the global maximum with this combined value.
  4. Return Extension Lengths to Parent:

    • For recursive purposes, return only the longer of left or right univalue path lengths to the parent, since paths can't split upward.
  5. Edge Cases:

    • If the tree is empty or has only one node, the maximum path is 0.

This DFS-based approach ensures all paths are checked once, giving an efficient solution with a time complexity of O(n), where n is the number of nodes.

Solutions

  • C++
  • Java
cpp
class Solution {
public:
    int longestPathResult;

    int calculate(TreeNode* node, int prevVal) {
        if (node == NULL) {
            return 0;
        }

        int leftPath = calculate(node->left, node->val);
        int rightPath = calculate(node->right, node->val);

        longestPathResult = max(longestPathResult, leftPath + rightPath);

        // Path count is zero if node value doesn't match with its parent value.
        // We include the node itself in the count by adding 1.
        return node->val == prevVal ? max(leftPath, rightPath) + 1 : 0;
    }

    int longestUnivaluePath(TreeNode* root) {
        // Initial parent value is set as -1, assuming no node value is negative.
        calculate(root, -1);
        
        return longestPathResult;
    }
};

The provided C++ solution addresses the problem of finding the longest univalue path in a binary tree. The univalue path refers to the longest path in which all nodes have the same value. The solution features a class Solution with a member function longestUnivaluePath.

  • The class contains an integer member longestPathResult used to store the maximum length of any univalue path found during the recursive traversal of the tree.

  • The function calculate is a recursive helper function designed to traverse the binary tree:

    • It accepts two parameters: a pointer to the current tree node node and the integer prevVal, which holds the value of the parent node.
    • The base case checks if the node pointer is NULL, returning 0 to indicate no path continuation.
    • For the left and right children of the current node, the function recursively calls itself, updating paths if the current node and its children have the same value.
    • The resultant path lengths for left and right sub-trees are evaluated, and the longestPathResult is updated accordingly to store the maximum length found.
    • The function returns the length of the longest univalue path including this node if the value matches with its parent; otherwise, returns zero.
  • The function longestUnivaluePath initiates the recursion:

    • It starts by calling calculate with the root node of the tree and an initial prevVal of -1 to handle the root appropriately.
    • Assuming no node values are negative allows differentiation between genuine node values and the initial condition.
    • Finally, it returns the value stored in longestPathResult, which would be the length of the longest univalue path.

This efficiently computes the longest univalue path by leveraging post-order traversal, ensuring each node and its descendants are completely processed before the node itself, thereby facilitating the update of path lengths correctly for the entire tree.

java
class Solution {
    int maxPath;

    int longestPath(TreeNode node, int val) {
        if (node == null) {
            return 0;
        }

        int leftPath = longestPath(node.left, node.val);
        int rightPath = longestPath(node.right, node.val);

        maxPath = Math.max(maxPath, leftPath + rightPath);

        if (node.val == val) {
            return Math.max(leftPath, rightPath) + 1;
        } else {
            return 0;
        }
    }

    public int longestUnivaluePath(TreeNode root) {
        longestPath(root, -1);
        return maxPath;
    }
}

The provided Java solution is designed to find the longest univalue path in a binary tree, where a univalue path is defined as a path in which all nodes have the same value. The solution uses a recursive helper method to track the longest path and updates a class variable maxPath to store the maximum length encountered during the traversal.

Here’s a breakdown of how the solution works:

  • A TreeNode class is assumed to be defined elsewhere with attributes for the node value val, and pointers to left and right child nodes left and right.

  • The main method longestUnivaluePath initializes the traversal by calling the helper method longestPath with the root of the tree and an arbitrary initial value.

  • The recursive method longestPath:

    • Checks if the current node is null. If so, it returns a path length of zero since there is no node to process.
    • Recursively computes the longest paths in the left and right subtrees where the subtree roots must match the value of the current node. This ensures that the paths consist of nodes with the same value.
    • Updates maxPath using the longest paths returned from the left and right subtrees. This is crucial as it tracks the current maximum univalue path encountered in the tree.
    • Returns the length of the longest path continuing from the current node, but only if the current node's value matches the target value (val). This allows connecting the paths from the child to the parent if they are part of the same univalue path.
    • If values don't match, it returns zero which essentially ends the path at that node.
  • After the recursive calls complete, maxPath holds the length of the longest univalue path found, and this value is returned by the longestUnivaluePath method.

In summary, this solution efficiently determines the longest univalue path in a binary tree using recursion to explore possible paths, and a max variable to keep track of the longest found so far, ensuring a comprehensive evaluation of all potential paths in the tree.

Comments

No comments yet.