LeetCode 1088 - Confusing Number II
In this problem, we are given an integer n, and we must count how many numbers in the range [1, n] are considered confusing numbers. A number becomes a confusing number if, after rotating every digit by 180 degrees, the resulting number is both: 1. Valid after rotation 2.
Difficulty: 🔴 Hard
Topics: Math, Backtracking
Solution
Problem Understanding
In this problem, we are given an integer n, and we must count how many numbers in the range [1, n] are considered confusing numbers.
A number becomes a confusing number if, after rotating every digit by 180 degrees, the resulting number is both:
- Valid after rotation
- Different from the original number
Only five digits remain valid after rotation:
| Original | Rotated |
|---|---|
| 0 | 0 |
| 1 | 1 |
| 6 | 9 |
| 8 | 8 |
| 9 | 6 |
Digits 2, 3, 4, 5, and 7 are invalid because they do not form recognizable digits after rotation.
The rotation process also reverses digit positions naturally. For example:
16becomes9189becomes688000becomes0008, which is treated as8
The task is not to generate the rotated numbers themselves, but to count how many valid confusing numbers exist from 1 through n.
The constraint 1 <= n <= 10^9 is very important. Since n can be as large as one billion, iterating through every number and checking whether it is confusing may become expensive. A smarter generation strategy is required.
Several edge cases are important:
- Numbers containing invalid digits must immediately be rejected.
- Numbers like
11,88, or69rotate into themselves and are therefore not confusing. - Leading zeros after rotation must be ignored correctly.
- The number
0itself is not included because the range starts from1.
Approaches
Brute Force Approach
The most straightforward solution is to iterate through every integer from 1 to n.
For each number:
- Extract every digit.
- Verify that all digits are rotatable.
- Build the rotated number by reversing digit order and applying the rotation mapping.
- Compare the rotated number with the original number.
- Count it if they differ.
This approach is correct because it explicitly checks every possible candidate.
However, it is inefficient. If n = 10^9, we may need to inspect one billion numbers. Even though each check only takes O(log n) time, the total runtime becomes far too large.
Optimal Approach, Backtracking Generation
The key observation is that only numbers composed of digits {0,1,6,8,9} can possibly be valid.
Instead of checking all numbers from 1 to n, we generate only numbers that contain valid digits.
This dramatically reduces the search space.
For example:
- A 9 digit number normally has
10^9possibilities. - Using only 5 valid digits gives at most
5^9 = 1,953,125possibilities.
This is much smaller and manageable.
We use depth first search (DFS) or backtracking to construct valid numbers digit by digit.
For each generated number:
- Ensure it does not exceed
n - Check whether its rotated form differs from the original
- Count it if confusing
- Continue extending it with more valid digits
This avoids exploring impossible candidates entirely.
Approach Comparison
| Approach | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| Brute Force | O(n log n) | O(log n) | Checks every number individually |
| Optimal | O(5^d × d) | O(d) | Generates only valid candidates, where d is number of digits |
Since n <= 10^9, the maximum number of digits is 10, making the backtracking solution efficient.
Algorithm Walkthrough
Step 1, Store Valid Rotations
We first define the rotation mapping:
{
0: 0,
1: 1,
6: 9,
8: 8,
9: 6
}
This allows us to rotate any valid digit efficiently.
Step 2, Define DFS Generation
We recursively build numbers using only valid digits.
At every recursive call:
- We have a partially built number
- We try appending one more valid digit
- We stop if the number exceeds
n
This ensures all generated numbers are potentially valid after rotation.
Step 3, Skip Leading Zero
We never start a number with 0.
Otherwise we would generate duplicates such as:
010010001
All of these represent the same number.
Step 4, Check Whether a Number Is Confusing
For each generated number:
- Rotate every digit
- Reverse digit order
- Construct the rotated number
- Compare against the original
If the rotated number differs, the number is confusing.
Step 5, Continue Recursion
After processing the current number, continue appending more digits recursively.
This explores the entire valid search space.
Why it works
The algorithm generates every number that could possibly be valid after rotation because it uses only rotatable digits.
No valid candidate is missed because DFS explores every combination of valid digits up to n.
No invalid candidate is included because numbers containing invalid digits are never generated.
The confusion check guarantees we count only numbers whose rotated form differs from the original.
Therefore, the algorithm correctly counts all confusing numbers in [1, n].
Python Solution
class Solution:
def confusingNumberII(self, n: int) -> int:
rotation = {
0: 0,
1: 1,
6: 9,
8: 8,
9: 6
}
valid_digits = [0, 1, 6, 8, 9]
def is_confusing(num: int) -> bool:
original = num
rotated = 0
while num > 0:
digit = num % 10
rotated = rotated * 10 + rotation[digit]
num //= 10
return rotated != original
def dfs(current: int) -> int:
count = 0
if current > n:
return 0
if current != 0 and is_confusing(current):
count += 1
for digit in valid_digits:
if current == 0 and digit == 0:
continue
next_number = current * 10 + digit
if next_number <= n:
count += dfs(next_number)
return count
return dfs(0)
The solution begins by storing the rotation mapping and the list of valid digits.
The is_confusing() helper function computes the rotated version of a number. It processes digits from right to left and builds the rotated number incrementally.
For example:
16- Process
6 → 9 - Process
1 → 1 - Result becomes
91
The DFS function generates all valid numbers recursively.
The recursion starts from 0, but 0 itself is never counted.
For every generated number:
- If it exceeds
n, recursion stops. - If it is confusing, increment the answer.
- Append every valid digit and continue searching.
The leading zero check prevents duplicate constructions.
Because only valid digits are used, every generated number is guaranteed rotatable.
Go Solution
func confusingNumberII(n int) int {
rotation := map[int]int{
0: 0,
1: 1,
6: 9,
8: 8,
9: 6,
}
validDigits := []int{0, 1, 6, 8, 9}
var isConfusing func(int) bool
isConfusing = func(num int) bool {
original := num
rotated := 0
for num > 0 {
digit := num % 10
rotated = rotated*10 + rotation[digit]
num /= 10
}
return rotated != original
}
var dfs func(int) int
dfs = func(current int) int {
if current > n {
return 0
}
count := 0
if current != 0 && isConfusing(current) {
count++
}
for _, digit := range validDigits {
if current == 0 && digit == 0 {
continue
}
nextNumber := current*10 + digit
if nextNumber <= n {
count += dfs(nextNumber)
}
}
return count
}
return dfs(0)
}
The Go implementation closely mirrors the Python solution.
The main difference is that Go uses explicit function variables for recursive closures.
The rotation mapping is implemented using map[int]int, and the DFS recursion returns the count accumulated from all branches.
Go integers safely handle the problem constraints because n <= 10^9.
Worked Examples
Example 1
Input: n = 20
The DFS generates numbers using digits {0,1,6,8,9}.
Generated numbers up to 20:
| Number | Rotated | Confusing? |
|---|---|---|
| 1 | 1 | No |
| 6 | 9 | Yes |
| 8 | 8 | No |
| 9 | 6 | Yes |
| 10 | 1 | Yes |
| 11 | 11 | No |
| 16 | 91 | Yes |
| 18 | 81 | Yes |
| 19 | 61 | Yes |
Total confusing numbers:
6
Example 2
Input: n = 100
Generated confusing numbers:
| Number | Rotated |
|---|---|
| 6 | 9 |
| 9 | 6 |
| 10 | 1 |
| 16 | 91 |
| 18 | 81 |
| 19 | 61 |
| 60 | 9 |
| 61 | 19 |
| 66 | 99 |
| 68 | 89 |
| 80 | 8 |
| 81 | 18 |
| 86 | 98 |
| 89 | 68 |
| 90 | 6 |
| 91 | 16 |
| 98 | 86 |
| 99 | 66 |
| 100 | 1 |
Total:
19
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(5^d × d) | Generates all valid digit combinations |
| Space | O(d) | DFS recursion depth |
Here, d is the number of digits in n.
For n <= 10^9, d <= 10.
The DFS generates at most:
5^1 + 5^2 + ... + 5^10
numbers, which is manageable.
Each confusion check takes O(d) time because we process each digit once.
The recursion stack depth is at most the number of digits.
Test Cases
sol = Solution()
assert sol.confusingNumberII(1) == 0 # no confusing numbers
assert sol.confusingNumberII(6) == 1 # only 6
assert sol.confusingNumberII(9) == 2 # 6 and 9
assert sol.confusingNumberII(10) == 3 # includes 10
assert sol.confusingNumberII(20) == 6 # provided example
assert sol.confusingNumberII(100) == 19 # provided example
assert sol.confusingNumberII(11) == 3 # 11 rotates to itself
assert sol.confusingNumberII(69) == 10 # includes many two-digit cases
assert sol.confusingNumberII(88) == 11 # 88 is not confusing
assert sol.confusingNumberII(99) == 18 # 99 rotates to 66
assert sol.confusingNumberII(1000) > 0 # larger boundary
assert sol.confusingNumberII(1000000000) > 0 # maximum constraint stress test
Test Summary
| Test | Why |
|---|---|
n = 1 |
Smallest possible input |
n = 6 |
Single confusing number |
n = 9 |
Multiple single digit confusing numbers |
n = 10 |
Leading zero after rotation |
n = 20 |
Provided example |
n = 100 |
Provided example |
n = 11 |
Number rotating to itself |
n = 69 |
Multi digit rotation behavior |
n = 88 |
Symmetric non confusing number |
n = 99 |
Rotated number changes completely |
n = 1000 |
Larger recursive generation |
n = 10^9 |
Maximum constraint stress test |
Edge Cases
One important edge case is numbers that rotate into themselves. Examples include 1, 8, 11, and 69. A naive implementation might incorrectly count them simply because they contain valid digits. The algorithm avoids this by explicitly constructing the rotated value and checking whether it differs from the original number.
Another important case involves leading zeros after rotation. For example, 10 rotates into 01, which should be interpreted as 1. If the implementation compared digit strings directly, it might incorrectly treat "01" differently from 1. The numeric construction naturally removes leading zeros, so the comparison remains correct.
A third important edge case is preventing numbers with leading zeros during DFS generation. Without this restriction, the recursion could generate duplicates like 01, 001, and 0001. The implementation prevents this by skipping digit 0 when constructing the first digit of a number.
Finally, the upper constraint n = 10^9 requires careful pruning. The DFS immediately stops recursion whenever the current number exceeds n, ensuring the algorithm remains efficient even at the maximum input size.