788. 旋转数字[记忆化搜索]

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=an1an2...a1a0
对每一位的数字进行如下分类:

  1. 翻转后不是一个数,如3,4,7,标记为-1
  2. 翻转后等于自己,如0,1,8,标记为1
  3. 翻转后不等于自己,如2,5,6,9,标记为2

默认标记为0

判断num是否为一个好数可以通过以下递归的方式判断

  1. a n − 1 a_{n-1} an1的标记为-1 a n − 2 . . . a 1 a 0 {a_{n-2}...{a_1}{a_0}} an2...a1a0的标记为-1,则num不是好数,且翻转后无法得到一个有效数,将num标记为-1
  2. a n − 1 a_{n-1} an1的标记为1 a n − 2 . . . a 1 a 0 {a_{n-2}...{a_1}{a_0}} an2...a1a0的标记为1,则num不是好数,但是翻转后得到的仍为自身,将num标记为1
  3. 其余情况,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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值