2翻转180°变成5挺离谱的。
思路
对于一个数num
,假设有n
位数字,
n
u
m
=
a
n
−
1
a
n
−
2
.
.
.
a
1
a
0
num = {a_{n-1}}{a_{n-2}...{a_1}{a_0}}
num=an−1an−2...a1a0。
对每一位的数字进行如下分类:
- 翻转后不是一个数,如
3,4,7
,标记为-1
- 翻转后等于自己,如
0,1,8
,标记为1
- 翻转后不等于自己,如
2,5,6,9
,标记为2
默认标记为0
判断num
是否为一个好数可以通过以下递归的方式判断
- 若
a
n
−
1
a_{n-1}
an−1的标记为
-1
或 a n − 2 . . . a 1 a 0 {a_{n-2}...{a_1}{a_0}} an−2...a1a0的标记为-1
,则num
不是好数,且翻转后无法得到一个有效数,将num
标记为-1
; - 若
a
n
−
1
a_{n-1}
an−1的标记为
1
且 a n − 2 . . . a 1 a 0 {a_{n-2}...{a_1}{a_0}} an−2...a1a0的标记为1
,则num
不是好数,但是翻转后得到的仍为自身,将num
标记为1
; - 其余情况,
num
是一个好数,翻转后的数不等于自身,将num
标记为2
。
因为需要1-N
中的所有数,所以可以通过记忆化来减少计算的复杂度,每次将一个数标记后进行记录,后续判断时去掉第一位的数一定已经是是标记过的了,直接拿来判断即可。
初始化时将0-9
进行手动标记。
代码如下:
class Solution {
private final static int[] MEMORY_ARRAY = new int[10001];
static {
Arrays.fill(MEMORY_ARRAY, 0);
MEMORY_ARRAY[0] = 1;
MEMORY_ARRAY[1] = 1;
MEMORY_ARRAY[2] = 2;
MEMORY_ARRAY[3] = -1;
MEMORY_ARRAY[4] = -1;
MEMORY_ARRAY[5] = 2;
MEMORY_ARRAY[6] = 2;
MEMORY_ARRAY[7] = -1;
MEMORY_ARRAY[8] = 1;
MEMORY_ARRAY[9] = 2;
}
private int ans;
public int rotatedDigits(int n) {
for (int i = 1; i <= n; i++) {
if (search(String.valueOf(i)) == 2){
ans++;
}
}
return ans;
}
private int search(String num){
//数字长度为0时认为是有效的
if (num.length() == 0){
return 2;
}
//记忆化搜索
int i = Integer.parseInt(num);
if (MEMORY_ARRAY[i] != 0){
return MEMORY_ARRAY[i];
}
//没搜索过进行一次判断
int firstNum = num.charAt(0) - '0';
int i1 = MEMORY_ARRAY[firstNum];
int i2 = search(num.substring(1));
int ret;
if (i1 == -1 || i2 == -1){
ret = -1;
} else if (i1 == 1 && i2 == 1){
ret = 1;
} else {
ret = 2;
}
MEMORY_ARRAY[i] = ret;
return ret;
}
}