题目:获取从1到n整数中1出现的次数,如n=13,则1,10,11,12,13中出现1的次数总共为6,则返回6
参数:范围的最大值n
方法一:递归方法(参考力扣答案)
思路:
f(n)为1-n范围内,这n个数中1出现的次数
首先将n分为两种情况:情况一:最高位为1(如1234);情况二:最高位不为1(如3234)
情况一:当最高位为1时(以1234为例):
①:将n分为两部分,最高位单独拿出来为1,定义为high;剩下的部分为234,定义为last;
②:获取到最高位的分位,为千分位,即定义pow=1000;
③将数据n定义两个范围:
1.1-999范围内,1的个数为f(pow-1);
2.1000-1234范围内:
1)首先只考虑千分位是1的个数:也就是1000、1001、1002...1234,即234+1,转换下为:last+1
2)其次考虑其他位数上的1的个数为:f(last)。
综上所述:情况一中1出现的次数为:f(pow-1)+last+1+f(last)
情况二:当最高为不为1时(以3234为例):
①:1-999范围内,1的个数依然为:f(pow-1);
②:1000-1999范围内:
1)只考虑千分位是1的个数为:1000、1001、1002...1999即1000个也就是pow;
2)其他位数上1的数量为:f(pow-1)
③:2000-2999范围内1的个数:f(pow-1),注意这里的千分位是2,所以不要考虑分两种情况
④:3000-3234范围内1的个数:f(last)
综上所述:情况二中1出现的次数为:pow+high*f(pow-1)+f(last);
测试结果:10ms;9288k
代码如下:
public int NumberOf1Between1AndN_Solution(int n){ //base case if(n<1){ return 0; } if(n<10){ return 1; } String s=String.valueOf(n); int high=s.charAt(0)-'0'; int pow=(int)Math.pow(10,s.length()-1); int last=n-high*pow; if(high==1){ return NumberOf1Between1AndN_Solution(pow-1)+last+1+NumberOf1Between1AndN_Solution(last); }else{ return pow+high*NumberOf1Between1AndN_Solution(pow-1)+NumberOf1Between1AndN_Solution(last); } }附上参考地址:
思路:挨个获取到每个数字,然后每个分位上判断1的数量,然后将所有数量进行相加(不推荐)
//①:遍历获取从1-n的每个数 //②:计算每个数包含1的数量:即先计算个位上的,n%10==1,数值相应加1 //③:将原数依次/10,按照②步骤计算十位上1数量,依次类推 public int NumberOf1Between1AndN_Solution(int n){ //base case if(n<1){ return 0; } if(n<10){ return 1; } int cnt=0; for(int i=n;i>0;i--){ for(int j=i;j>0;j/=10){ if(j%10==1){ cnt++; } } } return cnt; }