题解 | #整数中1出现的次数(从1到n整数中1出现的次数)#

整数中1出现的次数(从1到n整数中1出现的次数)

http://www.nowcoder.com/practice/bd7f978302044eee894445e244c7eee6

这道题很中规中矩,大致思路就是求某个数中1的个数+迭代

class Solution:
    def NumberOf1Between1AndN_Solution(self, n):
        # write code here
        def sumOf1(k):
            sum = 0
            while k > 0:
                sum += (1 if k % 10 == 1 else 0)
                k = int(k / 10)
            return sum

        f = 0
        for i in range(1, n + 1):
            f += sumOf1(i)
        return f

但上面的复杂度为nlogn级别,下面给出一种logn级别的方法。

class Solution:
    def NumberOf1Between1AndN_Solution(self, n):
        origin = n
        total = 0
        k = 1
        while n > 0:
            # 首先加上保守的部分
            total += origin // (k * 10) * k
            # 待比较的数字
            to_cmp_num = origin % (k * 10)
            # 和基数对比,大于基数,就要加额外的部分,额外的部分取它和基数的差值,但最大为基数k
            if to_cmp_num >= k:
                total += min(to_cmp_num - k + 1, k)
            n = int(n / 10)
            k *= 10
        return total

拿328举例
1、先看个位数,此时基数k=1
首先保守部分个数为328//(1x10) x 1 = 32,也就是个位数为1的保守统计个数为32个,分别是001,011,021...,311。这时待比较数字为328%(1x10)=8,之所以没有把321放进去,是害怕万一这个数为320。你也看到了,当个位数为0(也就是to_cmp_num=0 < 1)的时候,我们是不需要放的。由于to_cmp_num=8大于基数1了,所以就把这个额外的值加上,加多少呢?只能加1,也就是321这个数字。
2、再看十位数,此时基数k=10
首先保守部分个数为328//(10x10) x 10 = 30,也就是十位数为1的保守统计个数为30个,分别是010-019,110-119,210-219。这时待比较数字为328%(10x10)=28,之所以没有把310-319放进去,是害怕万一这个数,比如为308。你也看到了,当十位数为0(也就是to_cmp_num=8 < 10)的时候,我们也是不需要放的。由于to_cmp_num=28大于基数10了,所以就把这个额外的值加上,加多少呢?只能加10,也就是310-319这几个数字;如果是316呢,其实只能加7个。所以应该加差值个数,但最多只能加基数个,即10个。
3、再看百位数,此时基数k=100
首先保守部分个数为328//(100x10) x 10 = 0,也就是百位数为1的保守统计个数为0个。这时待比较数字为328%(100x10)=328,之所以没有把100-199放进去,是害怕万一这个数,比如为099。你也看到了,当百位数为0(也就是to_cmp_num=99 < 100)的时候,我们也是不需要放的。由于to_cmp_num=328大于基数100了,所以就把这个额外的值加上,加多少呢?只能加100,也就是100-199这几个数字;如果是166呢,其实只能加67个。所以应该加差值个数,但最多只能加基数个,即100个。

最后总结一下,先加上保守的部分(一定不会出问题的),再看待比较值to_cmp_num,这个数字为当前及以下位数组成的值。当前在个位时,即个位数值;当前为十位时,即十位和个位组成的值,以此类推。此时看to_cmp_num是否大于基数,小于基数,不用加了;大于基数,就加上它和基数的差值,但最大加的数不超过基数。

全部评论

相关推荐

10-17 23:18
已编辑
西北农林科技大学 Web前端
独行m:给25可以试试,但他只能给12,那就是纯纯的事精
秋招,不懂就问
点赞 评论 收藏
分享
10-10 01:10
已编辑
深圳大学 测试开发
面了100年面试不知...:六月到九月,四个项目一个实习,是魔丸吗
投了多少份简历才上岸
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务