一、题目:
输入一个整数 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. 数字 1 的个数 相同。
二、思路和代码:
思路一:
从1开始,将每个小于N的数都转换成字符形,统计这个字符中出现的1的数字,使用一个计数器累加起来,计数器就是最后的结果。
但是这个题标注困难,没这么简单,提交~ 超时~
//超出时间限制:
class Solution {
public:
int countDigitOne(int n)
{
int countr = 0;
for (long long i = 1; i <= n; i++) {
string str = to_string(i);//转换成字符形
countr += count(str.begin(), str.end(), '1');//使用count统计下来‘1’
}
return countr;
}
};
思路二:
找规律:所有的数字的每一位都可以分为小于1(0)、等于1(1)、大于1;据此有:
class Solution {
public:
int countDigitOne(int n) {
long long sum = 0;
long long base = 1;
long long cur,a,b;
while(base <=n ){
b = n % base;
a = n/base;
cur = a%10;
a /= 10;
if(cur>1) sum += (a+1)*base;
else if (cur==1) sum+=(a*base+b+1);
else sum +=a*base;
base *=10;
}
return sum;
}
};
ps:↑参考:香辣鸡排蛋包饭(一听就很好吃的样子)的python版本视频题解:
LeetCode刷题力扣题解 | 剑指Offer 43. 1~n 整数中 1 出现的次数 | 思路讲解及Python3代码实现。
据此完成的cpp版本,阿婆主讲得特别好。
办法三:
class Solution {
public:
int countDigitOne(int n){
int count = 0;
for (long long i = 1; i <= n; i *= 10) {
//(n/(i∗10))∗i 表示 (i*10) 位上 \text{'1'}’1’ 的个数+
//min(max((n mod (i*10))−i+1,0),i) 表示需要额外数的 (i*10)(i∗10) 位上 \text{'1'}’1’ 的个数
count += (n / (i*10)) * i + min(max(n % (i*10) - i + 1, 0LL), i);//0LL是一个longlong零。
}
return count;
}
};
//以11为例:循环2次:2+2: 只数个位:1:01、11、 指数十位1:10、11
//以111为例:循环3次:12+12+12
//......
结果:
怕什么真理无穷,进一步有进一步的欢喜!