File: cousins-in-binary-tree/solution.py

Date: 2026-06-06

Time: 16:08

Purpose

This file solves LeetCode 993: Cousins in Binary Tree. It determines whether two nodes in a binary tree are "cousins" — meaning they sit at the same depth but have different parents. The file is self-contained: it defines the tree node structure, the solution, a tree-building helper, and unit tests.

Key Components

TreeNode (line ~9)

Standard binary tree node with val, left, right. Used as the shared tree representation across this repo's binary tree problems.

Solution.isCousins(root, x, y) -> bool (line ~16)

The core algorithm. Takes a tree root and two node values, returns whether they're cousins. Contract: x and y are guaranteed to exist in the tree and be distinct (per LeetCode constraints). Returns False for None root.

buildtree(vals) -> Optional[TreeNode] (line ~53)

Test utility that constructs a binary tree from a level-order list, where None represents missing nodes. This is the standard LeetCode serialization format (e.g., [1, 2, 3, None, 4]).

TestCousins (line ~72)

Six test cases covering: different depths, actual cousins, siblings (same parent), root-child pair, and deep cousins.

Patterns

BFS with parent tracking. The queue stores (node, parent) tuples. Processing happens level-by-level using the level_size = len(queue) idiom — this is the standard way to do level-order traversal when you need to know when a level boundary is crossed.

Early termination within a level. After processing a full level, the code checks:

This avoids unnecessary work once the answer is determined.

Dependencies

Imports: collections.deque for BFS queue, typing.Optional for type hints, unittest for tests. No project-internal imports.

Imported by: The testsolution.py files listed in the "Imported By" section don't actually import *this* file — that list appears to be an artifact of the repo-wide cross-reference. The cousins-in-binary-tree/testsolution.py is the only true consumer, and the tests are already inline in this file.

Flow

1. Seed the BFS queue with (root, None) — root has no parent.

2. For each level, iterate exactly level_size times (snapshot of queue length at level start).

3. For each dequeued node, check if its value matches x or y, recording the parent if so.

4. Enqueue children with node as their parent.

5. After the level completes, apply the early-termination logic described above.

6. If the loop exhausts the tree without finding both, return False.

Invariants

Error Handling

Minimal — the None root check on line 30 is the only guard. No exceptions are raised. The algorithm trusts that x and y exist in the tree (matching LeetCode's guarantees). If they don't exist, it returns False after exhausting the tree.

Topics to Explore

Beliefs