A clear explanation of the Strobogrammatic Number problem using digit rotation rules and two pointers.
Problem Restatement
We are given a string num that represents an integer.
We need to return true if the number looks the same after being rotated 180 degrees. Otherwise, return false.
Only some digits are valid after rotation:
| Digit | Rotates To |
|---|---|
0 | 0 |
1 | 1 |
6 | 9 |
8 | 8 |
9 | 6 |
Digits like 2, 3, 4, 5, and 7 cannot appear in a valid rotated number.
The constraints say 1 <= num.length <= 50, num contains only digits, and there are no leading zeros except for "0" itself.
Input and Output
| Item | Meaning |
|---|---|
| Input | A string num |
| Output | True if num is strobogrammatic, otherwise False |
| Constraint | num contains only digits |
| Length | 1 <= len(num) <= 50 |
Example function shape:
def isStrobogrammatic(num: str) -> bool:
...Examples
Example 1:
num = "69"After rotation:
6 -> 9
9 -> 6The rotated number still matches the original shape.
So the answer is:
TrueExample 2:
num = "88"Both digits remain 8 after rotation.
So the answer is:
TrueExample 3:
num = "962"The digit 2 has no valid rotated form.
So the answer is:
FalseFirst Thought
One direct way is to build the rotated version of the string.
For each digit, replace it with its rotated digit. Then reverse the result, because rotating the whole number also swaps left and right positions.
If the final string equals the original string, the number is strobogrammatic.
class Solution:
def isStrobogrammatic(self, num: str) -> bool:
rotate = {
"0": "0",
"1": "1",
"6": "9",
"8": "8",
"9": "6",
}
rotated = []
for digit in num:
if digit not in rotate:
return False
rotated.append(rotate[digit])
return "".join(reversed(rotated)) == numThis works, but it builds an extra list.
We can check the same condition directly with two pointers.
Key Insight
When the number is rotated 180 degrees, two things happen:
- Each digit changes according to the rotation rule.
- The order is reversed.
So the leftmost digit must rotate into the rightmost digit.
The second digit must rotate into the second-to-last digit.
This is similar to checking a palindrome, but instead of checking equal characters, we check rotated pairs.
For example:
num = "69"The left digit is 6.
The right digit is 9.
Since:
rotate["6"] == "9"the pair is valid.
Algorithm
Create a rotation map:
rotate = {
"0": "0",
"1": "1",
"6": "9",
"8": "8",
"9": "6",
}Use two pointers:
left = 0
right = len(num) - 1While left <= right:
- Read
num[left]. - Read
num[right]. - If
num[left]cannot be rotated, returnFalse. - If
rotate[num[left]] != num[right], returnFalse. - Move both pointers inward.
If all pairs are valid, return True.
Correctness
The rotation of a full number reverses the positions of its digits.
Therefore, for every index left, the digit at left must rotate into the digit at the mirrored index right.
The algorithm checks exactly these mirrored pairs.
If a digit cannot be rotated, the number cannot be strobogrammatic, so returning False is correct.
If a digit rotates into a value different from its mirrored digit, the rotated number differs from the original number, so returning False is correct.
If every mirrored pair passes the check, then every digit becomes exactly the digit needed at its rotated position. Therefore, the whole number looks the same after rotation, so returning True is correct.
Complexity
| Metric | Value | Why |
|---|---|---|
| Time | O(n) | Each digit is checked at most once |
| Space | O(1) | The rotation map has fixed size |
Implementation
class Solution:
def isStrobogrammatic(self, num: str) -> bool:
rotate = {
"0": "0",
"1": "1",
"6": "9",
"8": "8",
"9": "6",
}
left = 0
right = len(num) - 1
while left <= right:
if num[left] not in rotate:
return False
if rotate[num[left]] != num[right]:
return False
left += 1
right -= 1
return TrueCode Explanation
The map stores the only valid rotations:
rotate = {
"0": "0",
"1": "1",
"6": "9",
"8": "8",
"9": "6",
}The two pointers start at both ends of the string:
left = 0
right = len(num) - 1For each mirrored pair, we first check whether the left digit can rotate:
if num[left] not in rotate:
return FalseThen we check whether its rotated value equals the right digit:
if rotate[num[left]] != num[right]:
return FalseIf the pair is valid, both pointers move inward:
left += 1
right -= 1If every pair is valid, the number is strobogrammatic:
return TrueTesting
def run_tests():
s = Solution()
assert s.isStrobogrammatic("69") is True
assert s.isStrobogrammatic("88") is True
assert s.isStrobogrammatic("962") is False
assert s.isStrobogrammatic("1") is True
assert s.isStrobogrammatic("2") is False
assert s.isStrobogrammatic("818") is True
assert s.isStrobogrammatic("619") is True
assert s.isStrobogrammatic("689") is True
print("all tests passed")
run_tests()| Test | Why |
|---|---|
"69" | Checks the 6 and 9 pair |
"88" | Checks unchanged digits |
"962" | Checks invalid digit rejection |
"1" | Checks one-character valid center |
"2" | Checks one-character invalid center |
"818" | Checks odd-length valid number |
"619" | Checks multiple rotated pairs |
"689" | Checks mixed valid rotations |