文章目录
- 一【题目类别】
- 二【题目难度】
- 三【题目编号】
- 四【题目描述】
- 五【题目示例】
- 六【解题思路】
- 七【题目提示】
- 八【时间频度】
- 九【代码实现】
- 十【提交结果】
一【题目类别】
- 数学
二【题目难度】
- 困难
三【题目编号】
- 233.数字 1 的个数
四【题目描述】
- 给定一个整数 n,计算所有小于等于 n 的非负整数中数字 1 出现的个数。
五【题目示例】
-
示例 1:
- 输入:n = 13
- 输出:6
-
示例 2:
- 输入:n = 0
- 输出:0
六【解题思路】
- 本题有一定难度,我第一次使用暴力解法, O ( n ) O(n) O(n)的时间复杂度,逐一判断每一个数字1的个数,最后超时了,显然需要换一个思路
- 为了降低时间复杂度,就不能一个一个的处理,而是要分批处理,主要思路是求出个、十、百……每一位1的个数,最后求和就可以了
- 当数位为 1 0 k 10^k 10k时(可能是个、十、百……任意一位),最后的 k k k位数字每 1 0 k + 1 10^{k+1} 10k+1个数字就会循环一次,而且其中包括 1 0 k 10^k 10k个1,那我们就要求 n n n中有多少个这样的循环,可用除法实现: ⌊ n 1 0 k + 1 ⌋ \left\lfloor\frac{n}{10^{k+1}}\right\rfloor ⌊10k+1n⌋,这样这一部分1的个数就是: ⌊ n 1 0 k + 1 ⌋ × 1 0 k \left\lfloor\frac{n}{10^{k+1}}\right\rfloor × 10^k ⌊10k+1n⌋×10k
- 刚才处理了在循环内1的个数,那么不在循环内的呢?也就是剩余的
n
m
o
d
1
0
k
+
1
n \bmod 10^{k+1}
nmod10k+1个数,这一部分1的个数应为
n
m
o
d
1
0
k
+
1
−
1
0
k
+
1
n \bmod 10^{k+1} - 10^k + 1
nmod10k+1−10k+1,剩余的这些数有几种情况:
- 上式的值小于0,那么就将此值调整为1出现0次,说明1没出现过
- 上式的值大于 1 0 k 10^k 10k,说明1出现了 1 0 k 10^k 10k个
- 还有另一个不确定的阈值,要根据位数去判断,如果上式的值不仅大于 1 0 k 10^k 10k,还大于此阈值,说明1出现的次数最多就是此阈值对应的出现次数,所以应该在两者中取最小
- 根据以上思路就可得到计算公式:
⌊ n 1 0 k + 1 ⌋ × 1 0 k + min ( max ( n m o d 1 0 k + 1 − 1 0 k + 1 , 0 ) , 1 0 k ) \left\lfloor\frac{n}{10^{k+1}}\right\rfloor \times 10^{k}+\min \left(\max \left(n \bmod 10^{k+1}-10^{k}+1,0\right), 10^{k}\right) ⌊10k+1n⌋×10k+min(max(nmod10k+1−10k+1,0),10k)
七【题目提示】
- 0 < = n < = 1 0 9 0 <= n <= 10^{9} 0<=n<=109
八【时间频度】
- 时间复杂度: O ( l o g n ) O(logn) O(logn),其中 n n n为传入参数的大小
- 空间复杂度: O ( 1 ) O(1) O(1)
九【代码实现】
- Java语言版
class Solution {
public int countDigitOne(int n) {
long mul = 1;
int res = 0;
for(int k = 0;mul<=n;k++){
res += (n / (mul * 10)) * mul + Math.min(Math.max(n % (mul * 10) - mul + 1,0),mul);
mul *= 10;
}
return res;
}
}
- C语言版
int countDigitOne(int n)
{
long mul = 1;
int res = 0;
while(mul <= n)
{
res += (n / (mul * 10)) * mul + fmin(fmax(n % (mul * 10) - mul + 1,0),mul);
mul *= 10;
}
return res;
}
- Python版
class Solution:
def countDigitOne(self, n: int) -> int:
mul = 1
res = 0
while mul <= n:
res += (n // (mul * 10)) * mul + min(max(n % (mul * 10) - mul + 1,0),mul)
mul *= 10
return res
十【提交结果】
-
Java语言版
-
C语言版
-
Python语言版