code36 写数字:

236 阅读1分钟

题目描述

  • 写数字:
  • 数位DP(太难了)
  • 给定一个正数N,表示你在纸上写下1~N所有的数字
  • 返回在书写的过程中,一共写下了多少个1
  • 举例:
  • N = 7 (1,2,3,4,5,6,7) 返回 1
  • N = 13 (1,2,3,4,5,6,7,8,9,10,11,12,13) 返回 6

code

public class Code36 {

    /**
     * 假设一个数是N,一共有K位
     * <p>
     * 最高位是1 :  (n % 10^(k-1) + 1) +  (10^(K-2) * (k-1) * 1)
     * 最高位不是1: 10(k-2次方) * (k-1) * first
     */
    public static int oneNumber(int num) {
        if (num < 1) {
            return 0;
        }
        // num -> 13625
        // len = 5位数
        int len = getLenOfNum(num);
        if (len == 1) {
            return 1;
        }
        // num 13625
        // tmp1 10000
        // num 7872328738273
        // tmp1 1000000000000
        int tmp1 = powerBaseOf10(len - 1);

        // num最高位 num / tmp1
        int first = num / tmp1;

        // 最高1 N % tmp1 + 1
        // 最高位first tmp1
        int firstOneNum = first == 1 ? num % tmp1 + 1 : tmp1;

        // 除去最高位之外,剩下1的数量
        // 最高位1 10(k-2次方) * (k-1) * 1
        // 最高位first 10(k-2次方) * (k-1) * first
        int otherOneNum = first * (len - 1) * (tmp1 / 10);

        return firstOneNum + otherOneNum + oneNumber(num % tmp1);
    }

    /**
     * 统计这个数有几位
     */
    public static int getLenOfNum(int num) {
        int len = 0;
        while (num != 0) {
            len++;
            num /= 10;
        }
        return len;
    }

    public static int powerBaseOf10(int base) {
        return (int) Math.pow(10, base);
    }
}