Foundations

Counting Bits

Return the popcount for every integer from 0 to n in O(n) time - popcount(i) = popcount(i >> 1) + (i & 1) reuses already-computed results by linking each number to its right-shifted half.

mediumFree~12 min

Problem

Compression codecs and Huffman encoders compute the population count for every symbol value in a range to build frequency tables. Given a non-negative integer n, return an array ans of length n+1 where ans[i] is the number of 1-bits in i, for every i from 0 to n inclusive.

Input: n = 2  → [0, 1, 1]
Input: n = 5  → [0, 1, 1, 2, 1, 2]

Verification

Trace the first few values by hand before running: ans[0]=0 (base), ans[1]=ans[0]+1=1, ans[2]=ans[1]+0=1, ans[3]=ans[1]+1=2, ans[4]=ans[2]+0=1, ans[5]=ans[2]+1=2. Writing out i >> 1 and i & 1 side by side for i=1..8 makes the recurrence immediately obvious.

Solution

Approach - Dynamic programming on the right-shifted subproblem.

The set-bit count of i relates cleanly to a smaller, already-solved number: i >> 1 is i with its lowest bit dropped, and dropping a bit removes either a 0 or a 1. That dropped bit is exactly i & 1 - 1 when i is odd, 0 when i is even. So popcount(i) = popcount(i >> 1) + (i & 1). Allocate ans = [0] * (n + 1), leave ans[0] = 0 as the base case, and fill forward from i = 1. Because i >> 1 is always strictly less than i, ans[i >> 1] is already computed by the time the loop reaches i, so each entry is filled in O(1) by a single table lookup plus the parity bit.

Trace i = 5 = 101. 5 >> 1 = 2 = 10, whose count ans[2] is 1, and 5 & 1 = 1 since 5 is odd, so ans[5] = 1 + 1 = 2. For i = 4 = 100, 4 >> 1 = 2, ans[2] = 1, and 4 & 1 = 0, giving ans[4] = 1. This reuse is the whole win: calling a standalone Kernighan popcount for each number would cost O(n log n) across the range, while linking each value to its half collapses the total to O(n).

Edge cases - n = 0 returns [0]; the loop body never runs and the base case stands. Forward iteration order is required so the i >> 1 dependency is always already filled.

Complexity - O(n) time, O(1) extra space - each of the n+1 entries is one lookup, and the output array is the required result, not auxiliary storage.

Done reading? Mark it so it sticks in your dashboard.

Next in CodingSingle Number II

Discussion (0)

Sign in to join the discussion.
No comments yet. Start the discussion.