牛客-剑指offer系列题解:整数中1出现的次数(从1到n整数中1出现的次数)

记录刷题的过程。牛客和力扣中都有相关题目,这里以牛客的题目描述为主。该系列默认采用python语言。

1、问题描述:
求出113的整数中1出现的次数,并算出1001300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。

2、数据结构:
数组

3、题解:
方法1:

# -*- coding:utf-8 -*-
class Solution:
    def NumberOf1Between1AndN_Solution(self, n):
        # write code here
        res ,i = 0,1
        while i <= n:
            divider = i * 10
            res += (n // divider) * i + min(max(n % divider - i + 1,0),i)
            i *= 10
        return res

方法2:递归

# -*- coding:utf-8 -*-
class Solution:
    def NumberOf1Between1AndN_Solution(self, n):
        # write code here
        return self.countvalue(n)
    def countvalue(self,n):
        if n <= 0:
            return 0
        s = str(n)
        high = int(s[0])
        Pow = 10 ** (len(s) - 1)
        last = n - high * Pow
        if high == 1:
            return self.countvalue(Pow - 1) + self.countvalue(last) + last + 1
        else:
            return Pow + high * self.countvalue(Pow - 1) + self.countvalue(last)

方法3:

class Solution:
    def NumberOf1Between1AndN_Solution(self, n):
        # write code here
        # 循环的出口是 highValue = 0
        # 我们从最低位开始一个位一个位的来寻找 1 的可能出现的 情况次数。
        # 一开始 精准度为1.高位低位中位 先赋值为1.
        preceise = 1
        highValue = 1
        lowValue = 1
        midValue = 1
        # 计数 后面的位数。
        count = 0
        # 计数 1 的次数和
        sumNum = 0
        # 循环的 出口是我们找不到最高位了,那么这个时候就说明,我们遍历到了 这个数字的最高位。
        while highValue != 0:
            # 高位 先将这个数 除以10 得到高位
            highValue = n // (preceise * 10)
            # 中位 先将这个数  与 10 取余。
            midValue = (n // preceise) % 10
            # 低位 先将这个数 除以 1 那么低位就是个位后面的,没有就是0.
            lowValue = n % preceise
            # 每遍历一次 向右移一位,那么就是说 精准度要乘以10.
            preceise *= 10
            # 如果这个数是0 的话,

            if midValue == 0:
                # 那么它就是高位的值,乘以 10^后面的位数 次方,但是这个时候 对于中位 来说 它是个位,后面没有位,所以是0,
                num = (highValue) * pow(10, count)
            # 如果这个数 大于1 的话,
            elif midValue > 1:
                # 那么它 就是 最高位加1 乘以 10^后面的位数 次方,
                num = (highValue + 1) * pow(10, count)
            else:
                # 否则的话 它就是等于1 的情况了,对于等于1 的1情况,又是比较特殊的情况,它需要 最高位 * 它10 的后面位数个数的次方,然后要加上我们低位 的数值再加 1, 原因在上面的分析中已经给出。
                num = highValue * pow(10, count) + (lowValue + 1)
            # 最后 我们1 出现的 次数 就是这 三个 num 的和,。
            sumNum += num
            # 没循环一次,这个三个就往左移一次吗,那么这个时候它们 后面的位数也就会 多一位。
            count += 1
        # 最后返回这个  次数和。
        return sumNum

4、复杂度分析:
方法1:
时间复杂度:O(log10 (N)) (以10为底)
空间复杂度:O(1)
方法2:
时间复杂度:O(N)
空间复杂度:O(N)
方法3:

发布了61 篇原创文章 · 获赞 10 · 访问量 2891

猜你喜欢

转载自blog.csdn.net/weixin_42042056/article/details/105747921