02
Path state (top-down) (Tree DFS Sub-pattern)
Carry information down a root-to-leaf path as a parameter, and check or record it when you reach a leaf.
Signals in the problem statement
- ›
"root-to-leaf path" with a sum, a number made of digits, or a list of paths
- ›
"no node on the path from the root is greater" (max so far)
- ›
"zigzag": the direction of the last step matters
What makes it different
Path Sum passes the remaining sum and checks only at leaves (values can be negative, so you can't stop early). Binary Tree Paths and Path Sum II keep a shared path and pop on the way back. Sum Root to Leaf Numbers carries cur * 10 + val. Count Good Nodes carries the max so far on the path, not the parent's value. Longest ZigZag carries the length for each direction you arrived from: continuing the zigzag adds 1, turning the same way twice restarts at 1.
Questions
ordered from “learn the idea” to “recognise it without help”- 1Path SumWalkthroughEasyBasic Anchor·LeetCode #112
- 2Binary Tree PathsWalkthroughEasyBasic Reinforcement·LeetCode #257
- 3Sum Root to Leaf NumbersWalkthroughMediumSlight Variation·LeetCode #129
- 4Path Sum IIWalkthroughMediumMedium·LeetCode #113
- 5Count Good Nodes in Binary TreeWalkthroughMediumPattern Transfer·LeetCode #1448
- 6Longest ZigZag Path in a Binary TreeWalkthroughMediumInterview-Level·LeetCode #1372
Template
path-state-template.cpp
// Top-down: carry the path's state as a parameter; check it at the leaves.
// Here: every root-to-leaf path whose sum is target (Path Sum II).
void walk(TreeNode* node, int remaining, vector<int>& path, vector<vector<int>>& out) {
if (!node) return;
path.push_back(node->val); // enter: add this node to the path
remaining -= node->val;
if (!node->left && !node->right) { // a leaf: the path is complete
if (remaining == 0) out.push_back(path);
} else {
walk(node->left, remaining, path, out);
walk(node->right, remaining, path, out);
}
path.pop_back(); // leave: undo, so the parent's path is clean
}
vector<vector<int>> pathSum(TreeNode* root, int target) {
vector<vector<int>> out;
vector<int> path;
walk(root, target, path, out);
return out;
}Remember this · Tree DFS
Trigger
Paths, heights, diameters, validating structure, ancestors, anything "for every subtree".
Think
If my left and right children already gave me their answers, how do I build mine?
Key question
What does my recursive function return, and what do I pass down?