题目大致意思是要求出1~N中数出现的1的个数。有种很直接的办法就是枚举1~N中的数,统计每个数共有多少位出现1,最后把结果累加起来。但这种办法在数据量大时用时过长,我们可以换个角度思考,把会被记录到总数的1按照位进行划分,统计第i位为1的在1~N中数字的个数,把得到的结果累加起来,就能得到1~N中数出现的1的个数。
举例
令N = 30710,从第一位开始统计每一位为1时数字的个数。
- 第一位为1时
为了不超过N,第一位的前面四位可以取0000,0001,...,3070,如果取3071就会得到30711超过30710。 - 第二位为1时
此时第二位前的三个数可以取000,001,...,306,最后一位可以取任意的0~9中的数。
当前三位取307时,最后一位就只能取0了 - 第三位取1时
此时前两位可以取00,01,...,30,而后两位可以取00,01,...,99
以此类推
规律
设我们要讨论的数是N,讨论N的一位(用a表示,讨论下一位时就让a乘以10),该位为now,N在now左侧的部分大小为left,右侧部分为right,该位为1的数字个数为ans,满足等式:
- 若
now = 0,ans = left * a - 若
now = 1,ans = left * a + right + 1 - 若
now > 1,ans = (left + 1) * a
实现
只要维护一个迭代过程中不断乘以10表示进一位的数a,left,now,right都可以通过除法和求余得到。
本文介绍了一种高效算法,用于计算1到N范围内所有数字中数字1出现的总次数。通过将问题分解为按位计数,避免了直接枚举的大规模计算,特别适用于大数据量场景。
105

被折叠的 条评论
为什么被折叠?



