Confusing Number II is a classic backtracking-by-construction problem. Instead of testing every number up to N, we only ever build numbers out of the digits that can possibly matter — a huge pruning win.
Problem. A confusing number is one that, when rotated 180°, becomes a different valid number. Only
the digits 0, 1, 6, 8, 9 stay valid after rotation (0→0, 1→1, 6→9, 8→8, 9→6); the others
(2, 3, 4, 5, 7) become garbage. Given N, count how many numbers in [1, N] are confusing.
Example: N = 20 → answer 6. The confusing numbers are 6, 9, 16, 18, 19, 20.
The slow way first
The obvious idea: loop x from 1 to N, rotate each x, and count the ones whose rotation is valid and different. That is O(N · digits) — fine for small N, but N can be up to a billion, so a full scan is hopeless.
The question to ask: most numbers can never be confusing — why visit them at all? Any number containing a 2, 3, 4, 5, or 7 is instantly disqualified. So rather than filtering after the fact, we should only ever construct numbers made of {0, 1, 6, 8, 9}.
The idea: build numbers from valid digits only
Run a DFS that grows a number one digit at a time. Start from 0, and at each step append one of the five rotatable digits, forming cur * 10 + d. The moment cur exceeds N, that whole branch is dead — prune it. For every number we build, rotate it; if the rotation differs from the original, it is confusing and we count it.
Because we never form a number with a bad digit, the search tree is tiny: at most five children per node, and bounded by the number of digits in N. We test only candidates that have a chance of being confusing.
Walk through it
Step through the animation with N = 20. The digit cells fill left to right as DFS builds a number. We try 1, see its rotation 1 is the same (not confusing), then extend it: 16 → 91, 18 → 81, 19 → 61 are all confusing. Whenever a number passes 20, the branch is pruned and we backtrack. The running count climbs as confusing numbers are found.
Pseudocode
ROT = {0:0, 1:1, 6:9, 8:8, 9:6} # digit -> its 180-degree image
dfs(cur):
if cur > N: return 0 # prune: too big
found = 1 if rotate(cur) != cur else 0
for d in {0,1,6,8,9}:
if cur == 0 and d == 0: skip # avoid a leading-zero loop
found += dfs(cur * 10 + d)
return found
answer = dfs(0) # subtract the 0 case, which is never in [1, N]The Python solution
ROT = {0:0, 1:1, 6:9, 8:8, 9:6}
def confusing_number_ii(n):
def dfs(cur):
if cur > n:
return 0
found = 1 if is_confusing(cur) else 0
for d in ROT:
if cur == 0 and d == 0:
continue
found += dfs(cur * 10 + d)
return found
return dfs(0) - (1 if is_confusing(0) else 0)ROTmaps each rotatable digit to the digit it becomes after a 180° flip.dfs(cur)explores the number built so far. The very first check,cur > n, prunes any branch that has already grown pastN.is_confusing(cur)rotatescur(flip each digit viaROT, reverse the order) and returnsTrueonly when the result differs fromcur. We add1for each confusing number.- The loop appends every valid next digit. The
cur == 0 and d == 0guard skips a pure leading zero, which would otherwise loop forever on0 → 0 → 0. - We start from
dfs(0)and subtract the0case at the end, since0is not in the range[1, N].
Complexity
| Case | Time | Notes |
|---|---|---|
| Brute force (scan 1..N) | O(N · D) (moderate) | rotate every number |
| DFS construction (this solution) | O(5^D) (moderate) | D = digits in N; only valid digits |
O(D) (moderate)Here D is the number of digits in N (at most 10 for a billion). Instead of touching all N numbers, we build only those made of five digits, so the work depends on the digit length, not the magnitude of N. The space is the recursion depth, O(D).
When this pattern shows up
When a range is enormous but only a few values can possibly qualify, do not iterate the range — construct the candidates directly with DFS/backtracking. The same move powers "numbers with repeated digits," "strobogrammatic numbers," and digit-DP style counting problems.
Two easy traps: forgetting the leading-zero guard (an infinite 0 → 0 recursion), and confusing
strobogrammatic with confusing. A strobogrammatic number reads the same after rotation; a confusing
number must read differently, so you count only when the rotation is not equal to the original.
Practice
For N = 20, when DFS builds 16, what is its rotation and does it count?
1. Why does DFS construction beat scanning 1..N?
2. Which digit set can appear in a confusing number?
3. When does a number count as confusing?
4. Why is the cur == 0 and d == 0 guard needed?