Given a number N
, return true
if and only if it is a confusing number, which satisfies the following condition:
We can rotate digits by 180 degrees to form new digits. When 0, 1, 6, 8, 9 are rotated 180 degrees, they become 0, 1, 9, 8, 6 respectively. When 2, 3, 4, 5 and 7 are rotated 180 degrees, they become invalid. A confusing number is a number that when rotated 180 degrees becomes a different number with each digit valid.
Example 1:
Input: 6
Output: true
Explanation:
We get `9` after rotating `6`, `9` is a valid number and `9!=6`.
Example 2:
Input: 89
Output: true
Explanation:
We get `68` after rotating `89`, `86` is a valid number and `86!=89`.
Example 3:
Input: 11
Output: false
Explanation:
We get `11` after rotating `11`, `11` is a valid number but the value remains the same, thus `11` is not a confusing number.
Example 4:
Input: 25
Output: false
Explanation:
We get an invalid number after rotating `25`.
Note:
0 <= N <= 10^9
- After the rotation we can ignore leading zeros, for example if after rotation we have
0008
then this number is considered as just8
.
這道題定義了一種迷惑數,將數字翻轉 180 度,其中 0, 1, 8 旋轉后保持不變,6變成9,9變成6,數字 2, 3, 4, 5, 和 7 旋轉后變為非法數字。若能將某個數翻轉后成為一個合法的新的數,就說這個數是迷惑數。這道題的難度並不大,就是考察的是遍歷整數各個位上的數字,使用一個 while 循環,然后用 mod10 取出當前最低位上的數字,將不合法的數字放入一個 HashSet 中,這樣直接在 HashSet 中查找一下當前數字是否存在,存在直接返回 false。不存在的話,則要進行翻轉,因為只有6和9兩個數字翻轉后會得到不同的數字,所以單獨判斷一下,然后將當前數字拼到 num 的最低位即可,最終拼成的 num 就是原數字 N 的翻轉,最后別忘了比較一下是否相同,參見代碼如下:
解法一:
class Solution {
public:
bool confusingNumber(int N) {
int num = 0, oldN = N;
unordered_set<int> invalid{{2, 3, 4, 5, 7}};
while (N > 0) {
int digit = N % 10;
if (invalid.count(digit)) return false;
if (digit == 6) digit = 9;
else if (digit == 9) digit = 6;
num = num * 10 + digit;
N /= 10;
}
return num != oldN;
}
};
這也可以用一個 HashMap 來建立所有的數字映射,然后還是用一個變量 oldN 來記錄原來的數字,然后遍歷N上的每一位數字,若其不在 HashMap 中,說明有數字無法翻轉,直接返回 false,否則就把翻轉后的數字加入 res,最后只要看 res 和 oldN 是否相等即可,參見代碼如下:
解法二:
class Solution {
public:
bool confusingNumber(int N) {
unordered_map<int, int> m{{0, 0}, {1, 1}, {6, 9}, {8, 8}, {9, 6}};
long oldN = N, res = 0;
while (N > 0) {
if (!m.count(N % 10)) return false;
res = res * 10 + m[N % 10];
N /= 10;
}
return res != oldN;
}
};
下面來看一種雙指針的解法,這里先用一個數組 rotate 來按位記錄每個數字翻轉后得到的數字,用 -1 來表示非法情況,然后將數字 N 轉為字符串,用兩個指針 left 和 right 分別指向開頭和末尾。用 while 循環進行遍歷,假如此時 left 和 right 中有任何一個指向的數字翻轉后是非法,直接返回 false。然后看 left 指向的數字翻轉后跟 right 指向的數字是否相同,若不同,則將 res 標記為 true,然后移動 left 和 right 指針,最終返回 res 即可,參見代碼如下:
解法三:
class Solution {
public:
bool confusingNumber(int N) {
bool res = false;
vector<int> rotate{0, 1, -1, -1, -1, -1, 9, -1, 8, 6};
string str = to_string(N);
int n = str.size(), left = 0, right = n - 1;
while (left <= right) {
if (rotate[str[left] - '0'] == -1 || rotate[str[right] - '0'] == -1) return false;
if (rotate[str[left] - '0'] != (str[right] - '0')) res = true;
++left; --right;
}
return res;
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/1056
類似題目:
參考資料:
https://leetcode.com/problems/confusing-number/