DSA
    advanced

    DP on Trees

    DP on Trees

    Tree Dynamic Programming applies DP bottom-up through a rooted tree, processing children before parents in a post-order DFS so each subtree is solved exactly once. Because trees are acyclic, there are no overlapping subproblems across branches — each child's result is computed once and aggregated upward to its parent. Classic problems include finding the tree diameter, the maximum path sum (where a path can branch through a node), and the maximum weight independent set (where chosen nodes cannot be adjacent). This visualization animates the Maximum Path Sum algorithm on a five-node binary tree, showing how each node separately tracks the best downward path to return to its parent and the best full path through itself that updates the global answer.

    ⏱ O(n)
    💾 O(n)
    Ready
    Global Max: —
    Visit order: []
    -10920157
    current computed↓N = maxPathDown from node

    DP on Trees: compute maxPathSum for Binary Tree. Process children BEFORE parents (post-order DFS).

    50%
    Live Variables
    approachpost-order DFS
    problemMax Path Sum

    Maximum independent set on a tree

    Sequence

    Order the steps of the take/skip tree DP.

    Tap a piece, then tap where it goes — or drag it. Tap the tray to take one back.

    1. 1Drop a step here
    2. 2Drop a step here
    3. 3Drop a step here
    4. 4Drop a step here
    5. 5Drop a step here
    5 pieces left to place

    Test your knowledge

    20 questions
    Question 1 of 20
    Score: 0

    In "Binary Tree Maximum Path Sum", why must we return a different value than we update?

    The short version

    Imagine a company org chart. To calculate the total bonus pool, each manager sums their team's bonuses and passes the total up. DP on trees computes values bottom-up from leaves to root.

    In more depth

    Bottom-Up Aggregation

    Tree DP processes nodes in post-order: handle children first, then compute parent's value.

    Common Pattern:

    def dfs(node):
        if not node: return base_case
        left = dfs(node.left)
        right = dfs(node.right)
        # Update global answer using both subtrees
        global_ans = max(global_ans, f(left, right, node))
        # Return single-path value to parent
        return g(left, right, node)

    Path vs Subtree:

    Path: Can only extend through ONE child
    Subtree: Can aggregate both children

    Rerooting:

    For "answer rooted at each node", compute once from a root, then propagate to children using parent info.

    Key Gotchas:

    Global max vs return value are often different
    Handle null children carefully
    Consider negative values (sometimes skipping is better)

    When to reach for this

    • Find maximum/minimum value involving tree paths
    • Aggregate values from subtrees
    • Each node makes a choice based on children
    • Keywords: 'path in tree', 'subtree sum', 'tree diameter'

    Interview Questions

    Facebook
    Amazon
    Microsoft
    Google
    Uber
    Facebook
    Netflix
    Airbnb
    Bloomberg
    Two Sigma
    Palantir

    Love this visualization?

    Sign up to track your progress, earn achievements, use the AI assistant, and access your personal learning dashboard.

    100% free • No credit card required