Free beta: 30 days of full access, no card needed.Sign up free

We use necessary cookies to run the site (sign-in and language). The contact and bug-report forms also use Google reCAPTCHA for spam protection, loaded only if you accept. Privacy policy

Field manual

DP on trees

O(n)

Walk the tree bottom-up (post-order): each node returns two numbers built from its children, one assuming the node is taken and one assuming it's skipped. The parent combines whichever fits its own rule.

Signals

best choice over a hierarchy or org chartcannot pick a node and its direct parent togetherpost-order: children settled before the parenteach node combines states from its children

Template

function maxNonAdjacent(node) {
    if (!node) return [0, 0]; // [incl, excl]
    let inclSum = node.value;
    let exclSum = 0;
    for (const child of node.children) {
        const [inclC, exclC] = maxNonAdjacent(child);
        inclSum += exclC;
        exclSum += Math.max(inclC, exclC);
    }
    return [inclSum, exclSum];
}

Looks similar, isn't

  • Tree traversal: A plain traversal just visits every node once with no memory of what a child decided. Tree DP has each node return one or more states, like included/excluded, built from what its children reported, so a parent can combine them under a rule such as never picking both a node and its child.

n up to 1e5 nodes, one post-order visit per node returning a couple numbers -> O(n): each node combines its children's states exactly once.

Learn this pattern