Taro Logo

Longest Univalue Path

Medium
Amazon logo
Amazon
1 view
Topics:
TreesRecursion

Given the root of a binary tree, return the length of the longest path, where each node in the path has the same value. This path may or may not pass through the root. The length of the path between two nodes is represented by the number of edges between them.

Example 1:

Consider the following binary tree:

      5
     / \
    4   5
   / \   \
  1   1   5

In this case, the longest path with the same value is 5 -> 5 -> 5, and the length of this path is 2 (number of edges).

Example 2:

Consider another binary tree:

      1
     / \
    4   5
   / \   \
  4   4   5

Here, the longest path with the same value is 4 -> 4 -> 4, and its length is 2.

Write a function that takes the root of a binary tree as input and returns the length of the longest path where all nodes in the path have the same value.

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.

Solution


Naive Approach

A brute force approach to this problem would involve traversing all possible paths within the binary tree and, for each path, checking if all nodes have the same value. We would then keep track of the longest such path. However, this method is highly inefficient as it requires generating and examining numerous paths, leading to a high time complexity.

Optimal Solution

The optimal solution uses a recursive approach, performing a depth-first traversal of the binary tree. For each node, we recursively find the length of the longest path with the same value in its left and right subtrees. We then check if the current node's value is the same as its children's values. If it is, we extend the path; otherwise, we start a new path. During the traversal, we maintain a global variable to store the maximum length found so far.

Algorithm:

  1. Initialize a global variable max_length to 0.
  2. Define a recursive function dfs(node) that returns the length of the longest path starting from the node, where all nodes have the same value as the starting node.
  3. In the dfs function:
    • If the node is None, return 0.
    • Recursively call dfs on the left and right children to get their respective lengths (left_length and right_length).
    • Check if the left child exists and has the same value as the current node. If so, increment left_length by 1.
    • Check if the right child exists and has the same value as the current node. If so, increment right_length by 1.
    • Update max_length with the maximum of its current value and left_length + right_length.
    • Return the maximum of left_length and right_length.
  4. Call the dfs function with the root node.
  5. Return max_length.

Code (Python):

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

class Solution:
    def longestUnivaluePath(self, root: TreeNode) -> int:
        self.max_length = 0

        def dfs(node):
            if not node:
                return 0

            left_length = dfs(node.left)
            right_length = dfs(node.right)

            left_arrow = 0
            right_arrow = 0

            if node.left and node.left.val == node.val:
                left_arrow = left_length + 1
            if node.right and node.right.val == node.val:
                right_arrow = right_length + 1

            self.max_length = max(self.max_length, left_arrow + right_arrow)
            return max(left_arrow, right_arrow)

        dfs(root)
        return self.max_length

Example:

Consider the tree:

      5
     / \
    4   5
   / \   \
  1   1   5

The algorithm will traverse the tree and find the longest univalue path (which is 5 -> 5 -> 5) with a length of 2.

Big O Analysis

  • Time Complexity: O(N), where N is the number of nodes in the binary tree. This is because we visit each node exactly once.
  • Space Complexity: O(H), where H is the height of the binary tree. In the worst case (skewed tree), H can be equal to N, resulting in O(N) space complexity. In the best case (balanced tree), H is log(N), resulting in O(log(N)) space complexity. This space is used by the call stack during the recursive calls.

Edge Cases

  • Empty Tree: If the root is None, the function should return 0, as there are no paths.
  • Single Node Tree: If the tree contains only one node, the function should return 0, as there are no edges.
  • Tree with all different values: The algorithm correctly handles the case where no two adjacent nodes have the same value, returning 0.
  • Skewed Tree: The algorithm also handles skewed trees correctly, as it traverses all nodes regardless of the tree's structure.