题目描述:
示例 1:
示例 2:
思路一:
- 暴力求出数字n中每一个数字,每一位是否为1,然后累加。
- 例如数字m, m%10先计算个位是否等于1,然后m = m/10,再次重复m%10计算十位是否等于1,依次重复,直到计算完所有位数。(超时)
代码实现:
class Solution {
public int countDigitOne(int n) {
return count(n);
}
public int count(int n) {
int result = 0;
for (int i = 1; i <= n; ++i) {
for (int j = i; j > 0; j /= 10) {
if (arr[j] == -1) arr[j] = j % 10;
if (j % 10 == 1) result++;
}
}
return result;
}
}
思路二:
-题目要求0~n所有数字中1出现的次数,除了暴力计算之外,可以通过求每一位上1出现的个数,累加的方式来获取,例如先计算个位有多少个1.再计算10位有多少个1... 百位,直到计算到n到位数。
那么如何计算不同位数的1出现的次数呢。
例如,数字131,
个位 数字出现1:1,11,21,31,41,51...91,101,111,121,131.
十位 数字出现1:10,11,12,13,14,15,16,17,18,19...110,111,112,113,114,115...119.
百位 数字出现1: 100,101,102.103...131.
观察上面的数字可以发现
个位以[0,9]区间循环,出现1次1.
十位数字以[10~99]区间循环,[10,19]区间出现10次1.[20~99]区间的数字十位肯定不是1。
百位数字以[100~999]区间循环,[100,199]区间出现100次1.[200~999]区间的数字百位肯定不是1.
同理,千位数字将以[1000,9999]区间循环,[1000,1999]出现1000次1.[2000~9999]区间的数字千位肯定不是1.
再来看131,百位是1的数字的个数,131 < 199,因此直接使用131-100 + 1= 131 + 1 = 32.
判断131小于199是因为再100~999区间的数字中,200~999百位都是不包含数字1的,100~199的每一个数字百位都包含1,因为是从100开始,所以是131-100 + 1;其它位同样计算即可。
代码实现:
class Solution {
public int countDigitOne(int n) {
int result = 0;
int idx = 1;
for (int i = 1; i <= n; i *= 10) {
int temp = n % (i * 10) - i + 1;
if (temp <= 0) {
temp = 0;
} else if (temp > i) {
temp = i;
}
result += (n / (i * 10)) * i + temp;
}
return result;
}
}