搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法、机器学习干货python
csdn:https://blog.csdn.net/baidu_31657889/git
github:https://github.com/aimi-cn/AILearnersgithub
这个系列是我在牛客网上刷《剑指Offer》的刷题笔记,旨在提高下本身的算法能力。
查看完整的剑指Offer算法题解析请点击CSDN和github连接:
剑指Offer完整习题解析CSDN地址
github地址算法
求出1~13的整数中1出现的次数,并算出1~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有一、十、十一、十二、13所以共出现5次,可是对于后面问题他就没辙了。ACMer但愿大家帮帮他,并把问题更加广泛化,能够很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。编程
方法1:最直观的是,对于1~n中的每一个整数,分别判断n中的1的个数,具体见《剑指offer》。这种方法的时间复杂度为O(N*logN),当N比较大的时候,通常会超时。微信
方法2:这种类别的题目,若是直观求解不行的话,那么一般是进行找规律,转化成一个数学问题。这道题目在《编程之美》上有着比较详细的描述,下面就结合一个实例进行具体的分析:机器学习
在分析以前,首先须要知道一个规律:学习
对于 n = 2134,要找到从1 ~ 2134这2134个数字中全部1的个数。咱们能够对2134进行逐位分析:spa
(1)在个位上,从1~2130,包含213个10,所以数字1出现了213次,剩下的数字213一、213二、213三、2134中个位数上只有2131包含树脂字1,剩下的都不包含。因此个位数上的数字1的总数为213 + 1 = 214。.net
(2)在十位上,从1 ~ 2100,包含了21个100,所以数字1出现了21 * 10 = 210次,剩下的数字从2101 ~ 2134,只有2110 ~ 2119这10个数字中十位的数字为1,因此十位上的数字1的总数为210 + 10 = 220。
(3)在百位上,从1 ~ 2000,包含了2个1000,所以数字1出现了2 * 100 = 200次,剩下的数字从2001 ~ 2134,只有2100 ~ 2134这35个数字中的百位的数字为1,因此百位数上数字1的总数为200 + 35= 235。
(4)在千位上,包含了0个10000,所以数字1出现了0 * 1000 = 0次,剩下的数字中只有1000 ~ 1999这1000个数字中的千位的数字为1,因此千位上的数字1的总数为1000。
所以从1 ~ 2134这n个数字中,数字出现的总的次数为 214 + 220 + 235 +1000 = 1669。
总结一下以上的步骤,能够获得这么一个规律:
对于数字n,计算它的第i(i从1开始,从右边开始计数)位数上包含的数字1的个数:
假设第i位上的数字为x的话,则
1.若是x > 1的话,则第i位数上包含的1的数目为:(高位数字 + 1)* 10 ^ (i-1) (其中高位数字是从i+1位一直到最高位数构成的数字)
2.若是x < 1的话,则第i位数上包含的1的数目为:(高位数字 )* 10 ^ (i-1)
3.若是x == 1的话,则第i位数上包含1的数目为:(高位数字) * 10 ^ (i-1) +(低位数字+1) (其中低位数字时从第i - 1位数一直到第1位数构成的数字)
python
代码实现方案:
# -*- coding:utf-8 -*-
class Solution:
def NumberOf1Between1AndN_Solution(self, n):
# write code here
if n < 1:
return 0
# mult位数 sumTime出现1的次数和
mult, sumTimes = 1, 0
while n//mult:
div, mod = divmod(n, mult*10)
curNum, curMod = divmod(mod, mult)
if curNum > 1:
sumTimes += div*mult + mult
elif curNum == 1:
sumTimes += div*mult + curMod + 1
else:
sumTimes += div*mult
mult = mult*10
return sumTimes复制代码
AIMI-CN AI学习交流群【1015286623】 获取更多AI资料
分享技术,乐享生活:咱们的公众号计算机视觉这件小事每周推送“AI”系列资讯类文章,欢迎您的关注!