Intuition
A node can't know it's a left child — but its parent can. Pass a flag down: when recursing left, mark it. Add the value only when the flagged node turns out to be a leaf.
When a node's contribution depends on how you arrived, pass that context down as a parameter. The node itself cannot tell whether it's a left or right child, so the parent supplies the answer at the call site. That trick — pushing context into the recursion — is what makes this a two-line change rather than a parent-pointer problem.
Approach
Parent tags the child
dfs(node, isLeft): if node is a leaf and isLeft, contribute its value.
Recurse both sides
dfs(left, True) + dfs(right, False). Right leaves contribute nothing but their subtrees may contain left leaves.
Leaf test
leaf = no children. A left child with a subtree is NOT a left leaf — the flag alone isn't enough.
Solution & live demo
Common pitfalls
Adding left children rather than left leaves
if node.left:
total += node.left.valif not node.left and not node.right:
return node.val if is_left else 0The question asks for leaves that happen to be left children, not every left child. An internal left node contributes nothing itself — only its leaf descendants do.
Checking leaf-ness from the parent
if node.left and not node.left.left and not node.left.right:
total += node.left.valdef dfs(node, is_left):
if not node.left and not node.right:
return node.val if is_left else 0It works, but it reaches two levels down and duplicates the leaf test for each side. Passing a flag lets each node answer for itself, which is far easier to extend to deeper questions.
Seeding the root as a left child
return dfs(root, True)
return dfs(root, False)
The root has no parent, so it's neither a left nor a right child. A single-node tree would otherwise report its value, when the correct answer is 0.
Edge cases
Root is nobody's child → 0.
Not a leaf — recursion continues inside it instead of adding.