题目链接
题目
输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。 例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。
示例 1:
输入:n = 12
输出:5
示例 2
输入:n = 13
输出:6
限制:
- 1 <= n < 2^31
- 注意:本题与主站 233 题相同:leetcode-cn.com/problems/nu…
题解
数字规律
- 时间复杂度 O(logn) : 循环内的计算操作使用 O(1) 时间;循环次数为数字 n 的位数,即 logn,因此循环使用 O(logn)时间。
- 空间复杂度 O(1) : 几个变量使用常数大小的额外空间。
将 1 ~ n 的个位、十位、百位、...的 1 出现次数相加,即为 1 出现的总次数。
高位 ,记为 high。当前位记为 cur。低位记为 low; 将 「10^i」称为 位因子 ,记为 digit 。 根据当前位 cur 值的不同,分为以下三种情况:
-
当 cur=0 时: 此位 1 的出现次数只由高位 high 决定,计算公式为:high×digit; 以 n=2304 为例,求 digit = 10(即十位)的 1 出现次数。数字划分为三部分,高位23,cur0,低位4出现1的数字范围0010-2219,只看高、低位为000-229,计算为:229 - 0 + 1 = 230,所以结果为23×10=230。
-
当 cur=1 时: 此位 1 的出现次数由高位 high 和低位 low 决定,计算公式为:high × digit + low + 1; 以 n=2314 为例,求 digit=10(即十位)的 1 出现次数。出现1的数字范围0010-2314,只看高、低位为000-234,计算为:234 - 0 + 1 = 235,所以结果为23 × 10 + 4 + 1 = 235。
-
当 cur>1 时: 此位 1 的出现次数由高位 high 决定,计算公式为:(high+1)×digit; 以 n=2324 为例,求 digit=10(即十位)的 1 出现次数。出现1的数字范围0010-2319,只看高、低位为000-239,计算为:239 - 0 + 1 = 240,所以结果为(23 + 1) × 10 = 240。
/**
* @param {number} n
* @return {number}
*/
var digitOneInNumber = function(n) {
let res = 0;
let high = Math.floor(n / 10),
cur = n % 10,
low = 0,
digit = 1;
while(high != 0 || cur != 0) {
if (cur == 0) res += high * digit;
else if (cur == 1) res += high * digit + low + 1;
else res += (high + 1) * digit;
low += cur * digit
cur = high % 10
high = Math.floor(high / 10)
digit *= 10
}
return res
};
枚举每一数位上 1 的个数
- 时间复杂度:O(logn)。n 包含的数位个数与 n 呈对数关系。
- 空间复杂度:O(1)。
/**
* @param {number} n
* @return {number}
*/
var countDigitOne = function(n) {
// mulk 表示 10^k
// 在下面的代码中,可以发现 k 并没有被直接使用到(都是使用 10^k)
// 但为了让代码看起来更加直观,这里保留了 k
let mulk = 1;
let ans = 0;
for (let k = 0; n >= mulk; ++k) {
ans += (Math.floor(n / (mulk * 10))) * mulk + Math.min(Math.max(n % (mulk * 10) - mulk + 1, 0), mulk);
mulk *= 10;
}
return ans;
};
累加
- 时间复杂度:O(nlogn)
- 空间复杂度:O(1)
/**
* @param {number} n
* @return {number}
*/
var countDigitOne = function(n) {
let number = 0;
for(let i = 1; i <= n; i++) {
number += numberOf1(i);
}
return number;
};
var numberOf1 = (n) => {
let number = 0;
while(n) {
if (n % 10 === 1) {
number++;
}
n = parseInt(n / 10);
}
return number;
}