LeetCode 1056 - Confusing Number
The problem asks us to determine whether a given integer becomes a different valid number after being rotated by 180 degrees. Not every digit remains valid after rotation.
Difficulty: 🟢 Easy
Topics: Math
Solution
Problem Understanding
The problem asks us to determine whether a given integer becomes a different valid number after being rotated by 180 degrees.
Not every digit remains valid after rotation. Only the following mappings are allowed:
| Original Digit | Rotated Digit |
|---|---|
| 0 | 0 |
| 1 | 1 |
| 6 | 9 |
| 8 | 8 |
| 9 | 6 |
Digits 2, 3, 4, 5, and 7 become invalid after rotation, which means any number containing one of these digits can never be a confusing number.
The important detail is that rotation also reverses the order of the digits. For example:
89becomes68916becomes619
This happens because when a number is physically rotated upside down, the last digit becomes the first digit in the rotated result.
A number is considered confusing if:
- Every digit remains valid after rotation.
- The rotated number is different from the original number.
If the rotated number is identical to the original number, then the number is not confusing.
The input is a single integer n where:
0 <= n <= 10^9
Since the maximum value is only one billion, the number contains at most 10 digits. This tells us that even digit by digit processing is extremely fast.
There are several important edge cases:
- Numbers containing invalid digits such as
2or7must immediately returnfalse. - Numbers like
11or69rotate into themselves, so they are not confusing. - Leading zeros in the rotated result should be ignored. For example,
8000rotates to0008, which is simply8. - The value
0is not confusing because it rotates to itself.
Approaches
Brute Force Approach
A brute force style solution would simulate the entire rotation process by converting the number into a string, reversing it, rotating each digit, and constructing a new string.
The algorithm would:
- Convert the number to a string.
- Reverse the string.
- Replace each digit using the rotation mapping.
- If any digit is invalid, return
false. - Convert the rotated string back into an integer.
- Compare it with the original number.
This approach is correct because it exactly models the rotation process.
However, string manipulation introduces extra overhead. While the constraints are small enough that this still works efficiently, we can do better with direct mathematical digit processing.
Optimal Approach
The key observation is that we can build the rotated number mathematically while extracting digits from right to left.
When we repeatedly take the last digit using % 10, we naturally process digits in reverse order, which perfectly matches how rotated numbers are formed.
For example:
- Original number:
89 - Extract digits from right to left:
9, then8 - Rotate them:
6, then8 - Build result:
68
This avoids string conversion entirely and uses only integer arithmetic.
We maintain:
- A hash map containing valid rotations
- A variable storing the rotated number
If we encounter an invalid digit, we immediately return false.
At the end, we compare the rotated number with the original.
Approach Comparison
| Approach | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| Brute Force | O(d) | O(d) | Uses string conversion and reversal |
| Optimal | O(d) | O(1) | Uses pure mathematical digit processing |
Here, d represents the number of digits in n.
Algorithm Walkthrough
- Create a mapping for all valid rotated digits.
We store:
{
0: 0,
1: 1,
6: 9,
8: 8,
9: 6
}
This allows constant time lookup for each digit. 2. Store the original number.
We need the original value later so we can compare it against the rotated result. 3. Initialize a variable to build the rotated number.
Start with:
rotated = 0
- Process digits one by one from right to left.
While the number is greater than zero:
- Extract the last digit using
% 10 - Remove the last digit using
// 10
- Validate the digit.
If the digit is not in the rotation map, immediately return false.
This handles invalid digits like 2, 3, 4, 5, and 7.
6. Build the rotated number.
Append the rotated digit using:
rotated = rotated * 10 + rotated_digit
Multiplying by 10 shifts existing digits left so the new digit can be appended. 7. Compare the rotated number with the original.
If they are different, return true.
Otherwise return false.
Why it works
The algorithm processes digits from right to left, which naturally matches the reversal caused by rotating the number. Each extracted digit is transformed using the valid rotation mapping and appended to the new number in the correct order.
If every digit is valid and the final rotated number differs from the original, then the number satisfies the exact definition of a confusing number.
Python Solution
class Solution:
def confusingNumber(self, n: int) -> bool:
rotation_map = {
0: 0,
1: 1,
6: 9,
8: 8,
9: 6
}
original = n
rotated = 0
while n > 0:
digit = n % 10
if digit not in rotation_map:
return False
rotated = rotated * 10 + rotation_map[digit]
n //= 10
return rotated != original
The solution begins by defining a dictionary that stores the valid digit rotations. This dictionary serves two purposes: it validates digits and provides the transformed value.
We store the original number because the variable n will be modified during digit extraction.
The loop repeatedly extracts the last digit using modulo arithmetic. If a digit is invalid, the function immediately returns False.
Otherwise, the rotated digit is appended to the result. Since digits are processed from right to left, the constructed number automatically has the correct rotated order.
Finally, the rotated number is compared against the original. If they differ, the number is confusing.
Go Solution
func confusingNumber(n int) bool {
rotationMap := map[int]int{
0: 0,
1: 1,
6: 9,
8: 8,
9: 6,
}
original := n
rotated := 0
for n > 0 {
digit := n % 10
rotatedDigit, exists := rotationMap[digit]
if !exists {
return false
}
rotated = rotated*10 + rotatedDigit
n /= 10
}
return rotated != original
}
The Go implementation follows the same logic as the Python version but uses Go's map syntax and explicit existence checking.
One notable difference is that Go requires checking whether a key exists in the map using:
value, exists := map[key]
This avoids accidentally treating missing digits as valid zero values.
Since the constraints are small, integer overflow is not a concern in Go.
Worked Examples
Example 1: n = 6
Expected output: true
| Step | Current n | Extracted Digit | Rotated Digit | Rotated Number |
|---|---|---|---|---|
| Start | 6 | - | - | 0 |
| 1 | 6 | 6 | 9 | 9 |
Final comparison:
- Original =
6 - Rotated =
9
Since 9 != 6, return true.
Example 2: n = 89
Expected output: true
| Step | Current n | Extracted Digit | Rotated Digit | Rotated Number |
|---|---|---|---|---|
| Start | 89 | - | - | 0 |
| 1 | 89 | 9 | 6 | 6 |
| 2 | 8 | 8 | 8 | 68 |
Final comparison:
- Original =
89 - Rotated =
68
Since 68 != 89, return true.
Example 3: n = 11
Expected output: false
| Step | Current n | Extracted Digit | Rotated Digit | Rotated Number |
|---|---|---|---|---|
| Start | 11 | - | - | 0 |
| 1 | 11 | 1 | 1 | 1 |
| 2 | 1 | 1 | 1 | 11 |
Final comparison:
- Original =
11 - Rotated =
11
Since the value remains unchanged, return false.
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(d) | We process each digit exactly once |
| Space | O(1) | The rotation map has constant size |
The algorithm scans through the digits of the number once. Since a number with value up to 10^9 contains at most 10 digits, the runtime is extremely small.
The space usage is constant because the rotation mapping never grows with input size.
Test Cases
solution = Solution()
assert solution.confusingNumber(6) == True # Single digit that changes
assert solution.confusingNumber(89) == True # Multiple valid digits
assert solution.confusingNumber(11) == False # Rotates to itself
assert solution.confusingNumber(0) == False # Zero remains zero
assert solution.confusingNumber(1) == False # One remains one
assert solution.confusingNumber(8) == False # Eight remains eight
assert solution.confusingNumber(69) == False # Rotates to itself
assert solution.confusingNumber(96) == False # Rotates to itself
assert solution.confusingNumber(10) == True # Leading zero after rotation
assert solution.confusingNumber(8000) == True # Rotates to 8
assert solution.confusingNumber(2) == False # Invalid digit
assert solution.confusingNumber(25) == False # Contains invalid digit
assert solution.confusingNumber(347) == False # Multiple invalid digits
assert solution.confusingNumber(916) == True # Valid confusing number
assert solution.confusingNumber(9996) == True # Larger valid case
assert solution.confusingNumber(1000000000) == True # Large boundary case
Test Summary
| Test | Why |
|---|---|
6 |
Simplest confusing number |
89 |
Multi digit valid rotation |
11 |
Rotates to same number |
0 |
Edge case for zero |
1 |
Single digit unchanged |
8 |
Symmetric digit |
69 |
Rotates into itself |
96 |
Another self rotating case |
10 |
Leading zeros after rotation |
8000 |
Multiple leading zeros |
2 |
Invalid digit |
25 |
Mixed valid and invalid digits |
347 |
Entirely invalid rotation |
916 |
Larger confusing number |
9996 |
Multiple reversible digits |
1000000000 |
Maximum constraint boundary |
Edge Cases
One important edge case is numbers containing invalid digits such as 2, 3, 4, 5, or 7. These digits do not have valid rotated forms, so the entire number immediately becomes invalid. A naive implementation might accidentally ignore these digits or map them incorrectly. The solution prevents this by checking whether every digit exists in the rotation map before building the rotated number.
Another important case is numbers that rotate into themselves. Examples include 11, 69, 88, and 96. Even though every digit is valid, the problem requires the rotated value to be different from the original number. The implementation correctly handles this by comparing the final rotated result against the original input.
Leading zeros are another subtle source of bugs. For example, 8000 rotates to 0008, which should be interpreted as 8. String based implementations can mishandle this if they preserve unnecessary zeros. The mathematical construction used here naturally ignores leading zeros because integers do not store them.
The input 0 is also special. Since it rotates to itself, it is not confusing. The loop does not execute for 0, leaving the rotated value as 0, and the final comparison correctly returns False.