【LeetCode】233. Number of Digit One 数字 1 的个数(Hard)(JAVA)
题目地址: https://leetcode.com/problems/number-of-digit-one/
题目描述:
Given an integer n, count the total number of digit 1 appearing in all non-negative integers less than or equal to n.
Example:
Input: 13
Output: 6
Explanation: Digit 1 occurred in the following numbers: 1, 10, 11, 12, 13.
题目大意
给定一个整数 n,计算所有小于等于 n 的非负整数中数字 1 出现的个数。
解题方法
- 要求所有小于等于 n 的非负整数中数字 1 出现的个数,可以先计算所有小于 10^k 中非负整数中数字 1 出现的个数。
- 计算小于 10^k 中非负整数中数字 1 出现的个数:可以拆分为两个,1、 1开头的个数(小于10^(k - 1) 的数算作 0 开头的数),2、非1开头的个数
- 小于 10^k 中 1 开头的个数: 10^(k - 1) 个,这里 1 开头的数中,所有的开头的 1 的个数可以很快计算出来,10^(k - 1) 个
- 小于 10^k 中非 1 开头数要计算 1 的个数,就是计算 10^(k - 2) 里面的 1 的个数然后再乘以非 1 开头的数总共有 10 个
- 这样就可以通过递归计算出小于 10^k 中非负整数中数字 1 出现的个数
- 最后要计算 n,其实就是计算 n 后面的 0 的个数,然后看 n 首位的数字,分别计算就行了
class Solution {
Map<Integer, Integer> map = new HashMap<>();
public int countDigitOne(int n) {
if (n <= 0) return 0;
if (n < 10) return 1;
long pro = 10;
int count = 1;
while (pro <= n) {
pro *= 10;
count++;
}
pro /= 10;
count--;
int high = (int) (n / pro);
int res = (int) Math.min(n - pro + 1, pro);
int pre = getNum(count);
res += high * pre;
res += countDigitOne((int) (n % pro));
return res;
}
// < 10^n
public int getNum(int n) {
Integer temp = map.get(n);
if (temp != null) return temp;
if (n == 1) return 1;
int pre = getNum(n - 1);
int res = (int) Math.pow(10, n - 1) + pre * 10;
map.put(n, res);
return res;
}
}
执行耗时:0 ms,击败了100.00% 的Java用户
内存消耗:35.2 MB,击败了71.77% 的Java用户