计算整数n的所有因子之和_算法系列之从1到n整数中1出现的次数

该博客介绍了如何计算从1到n的整数中1出现的次数,通过两种解法详细解析了计算过程。解法1是逐个数统计1的个数,解法2则是通过分析数的各个位来优化计算。同时,文章讨论了因子之和的问题,提供了解决思路。
摘要由CSDN通过智能技术生成

题目来源 剑指offer

01 题目

输入一个整数n,求从1到n,这n个十进制整数1出现的次数。例如,12, 那么1到12中包含1的数字有{1,10,11,12},其中11包含两个1,故总共5个数。

02 解法1

看到这道题,我们的第一反应很容易想到,从1遍历到n,然后计算每个数中1的个数。

64f53cf23c8b9db41b28d0288265ee72.png

我们分析一下时间复杂度,从1到n遍历这个值的时间消耗是 o(n)。

计算每个数中的1的个数花费的时间是log(n)。log(n)的不是一个精确的概念,只是说随着n的值的增大,它的整体时间和空间复杂度成对数式增长,是一个相对的概念。

03 解法2

解法1很容易理解不再赘述,我们重点讲解解法2.

以 214为例

  • 个位数出现1的次数计算。

个位数的范围是0-9,它的值是一直在0-9之间循环。0-9出现一次。说明个位数出现一次1。那么214出现了多少次完整的0-9呢。

214/10=21次。个位本身是4,4>1。

 21 + 1 = 22次。
  • 十位出现1的次数计算,(只看十位数,个位数已经计算,百位数接下来下次计算)

十位数的范围同样是0-9,它出现几次0-9呢,看它的前一位 214。说明2次进位 两次循环0-9。

10(0-9),11(0-9),12(0-9),13(0-9),14(0-9),15(0-9),16(0-9),17(0-9),18(0-9),19(0-9)

[注* 10(0-9)表示 100,101,102,103,104,105,106,107,108,109,其他雷同]

和0(0-9),1(0-9),2(0-9),3(0-9),4(0-9),5(0-9),6(0-9),7(0-9),8(0-9)

那么此时十位出现1的次数是2*10,(为什么是10,因为每次10进制的一个数,个位数可以出现十次,如10,11,12,13,14,15,16,17,18,19)

我们再来看,百位为2时,十位本身是1,但是它不能按10次来计算,因为214个位为4,只有210,211,212,213,214.这几个数。所以是5位。为(214%10 + 1)

总的十位数出现的1的次数为 (214/100)*10 + (214 % 10 + 1)

另:如果十位数大于1,那么次数就是(214/100)*10 + 10。思考下为什么呢哈哈

  • 百位数出现的次数计算

百位数出现一次1,则会有100个1。从100,到199,可以自行推算一下。因为百位已经是最后一位,所以只会有一次1出现。

故百位出现1的次数为 100

04 总结

数值为n

1.每个位出现1的次数,是以所处的位基准数计算的。如个位数出现一次1,就是1。十位数出现一次1,就是10次1。百位数出现一次1,就是100次1。

我么用一个base表示所处的位数。

2.看位数中出现几次(0-9),要看它前面的数值。如2233。

个位数出现223次(0-9) 223((n/base) * 1)次1 base = 1

十位数出现22次(0-9)220次((n/base) * 10) 1 base = 10

百位数出现2次(0-9)200次((n/base) * 100)1 base = 100

然后再看位数本身的值。个位数3,说明多余了一次1 (base=1)

十位数是3大于1,说明多余出现了10(base=10)次1 .

百位数是2大于1,说明多余出现了100(base=100)次1.

千位数是2大于1,说明多余出现了1000(base=1000)次1. 然后所有相加得结果。

public static int countDigit1(int n) { int base = 1;// 表示所在的位数 int count = 0; int round = n; // 计算每次除以base后的值 while (round > 0) { int reminder = round % 10; round /= 10; count += round * base; if (reminder > 1) { count += base; } else if (reminder == 1) { count += (n % base) + 1; } base *= 10; } return count;}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值