File: counting-bits/solution.py

Date: 2026-06-06

Time: 16:07

counting-bits/solution.py

Purpose

This file solves LeetCode 338 — Counting Bits. Given a non-negative integer n, it returns an array ans of length n+1 where ans[i] is the number of 1 bits (popcount) in the binary representation of i. It's one of ~500+ solutions in the leetcode-implementations repo, each in its own directory with the standard solution.py / test_solution.py / review.md / plan.md layout.

Key Components

countBits(n: int) -> list[int] — The sole public function. Contract: given n >= 0, returns a list of n+1 integers where index i holds bin(i).count('1').

Patterns

The solution uses a dynamic programming recurrence based on bit-shifting:


ans[i] = ans[i >> 1] + (i & 1)

This decomposes the popcount of i into two parts:

1. ans[i >> 1] — the popcount of i with its least-significant bit removed (i.e., i // 2). Since i >> 1 < i, this value is already computed.

2. (i & 1) — whether the least-significant bit of i is set (0 or 1).

This is the "last set bit" DP variant. An alternative recurrence uses ans[i & (i-1)] (Brian Kernighan's trick to drop the lowest set bit), but the right-shift approach avoids the subtraction.

The DP builds bottom-up from index 1, with the base case ans[0] = 0 established by the [0] * (n + 1) initialization.

Dependencies

Imports: None — pure Python, no standard library or third-party dependencies.

Imported by: The counting-bits/test_solution.py file imports countBits directly. The massive "Imported By" list in the prompt is misleading — those are unrelated test files that happen to share a common test harness import pattern, not actual consumers of countBits.

Flow

1. Allocate a zero-initialized list of size n+1.

2. Iterate i from 1 to n inclusive.

3. For each i, look up the already-computed popcount of i >> 1 and add the LSB of i.

4. Return the completed array.

Time complexity: O(n). Space complexity: O(n) for the output (no auxiliary space beyond that).

Invariants

Error Handling

None. Negative n would produce [0] * (n+1) which is an empty list for n = -1 or would error for more negative values due to list construction — but the LeetCode constraint guarantees 0 <= n <= 10^5.

Topics to Explore

Beliefs