这里主要记录一下时间复杂度为 O(数的位数) 的方法,原作者大神的解答在:https://leetcode-cn.com/problems/1nzheng-shu-zhong-1chu-xian-de-ci-shu-lcof/solution/mian-shi-ti-43-1n-zheng-shu-zhong-1-chu-xian-de-2/

对于一个整数,它的位数是多少位呢?不妨举几个例子:

  • 如果是99,很显然,它是两位
  • 100,是三位

可以用log10(m),即以10为底,m为给出的数来表示一个数能有多少位,如果m=99,那么这个式子约等于2,即两位;如果m=999,那这个式子差不多是3;如果m在(99, 999)范围内,那这个式子约等于2,也就是说我们可以用这个式子来大约的估计给出的数能有多少位。

得到了数m的位数,下面的算法就能做到在O(log(10)m)的时间内完成计算。

开始分析

对于一个数的每一位,把它分成三种情况:

  • 为0
  • 为1
  • 为2-9

用cur表示走到了当前位数,high表示高位,low表示低位,具体说明见下图:

现在分类讨论, 先看当前位数值是0的情况 ,我们以2304为例,假设当前位数是倒数第二位:

此时cur位置为1的数有多少个呢?固定cur位置为1,然后观察其他几位数的范围:

cur位置固定为1,那么想要统计数字中1出现的次数,最小值肯定是0010,因为0009就没有1了,最大值就是2219,因为十位(cur)固定为1,百位千位不能超过23,如果百位千位是23那就是2319了,比给出的数2304大,不符合题意。

这种情况下有多少个数字带1呢?其实就是看0010-2219,固定十位为1,其他位在这个范围内有多少种组合,不妨先用穷举法分析一下:

  • 固定千位为0(十位为始终1),那么从0010开始,一共有100个数里面带1:0010、0011、0012、…、0110、0111、0112、…、0910、0911、0912、…、0919,共100种。其实就是把千位0和十位1扣去,看剩下的百位和个位有多少种组合,很显然从00-99有100种组合;
  • 固定千位为1(十位为始终1),那么从1010开始,还是有100个数里面带1,原理和上面一样,把千位1和十位1扣去,还是百位和个位00-99的组合;
  • 固定千位为2(十位为始终1),那么从2010开始,一直到2219结束,一共有30个数里面带1,原理同上。
  • 综上,当cur到十位时,一共有 100+100+30 = 230 个数里面带1
  • 其实一个更简便的思路是,0010-2219,现在不是固定十位为1吗?那我就把十位扣去,剩下000-229,直接得出有230个数里面带1。

因此得出规律,如果cur当前位数的值为0,那么一共有 高位*cur所在位数(上例为10位) 的数带1,对上例来说,高位是23,cur所在位数是10位,那么一共有23*10=230个数里面带1。

再看当前位数值为1的情况 ,以2314为例,假设cur为倒数第二位,那么0010-2314范围内有多少个数带1呢?其实就是把十位扣出,剩下000-234,也就是有235个数会带1。

因此得出规律,如果cur当前位数的值为1,那么一共有 高位*cur所在位数(上例为10位) + 1 + 低位 的数带1,对上例来说,高位是23,cur所在位数是10位,低位是4,那么一共有23*10 + 1 + 4=235个数里面带1。

最后是当前位数值为[2-9]的情况,以2324为例,假设cur为倒数第二位,那么0010-2319范围内有多少个数带1呢?计算方法同上,把十位扣出,剩下000-239,也就是有240个数会带1。

因此得出规律,如果cur当前位数的值为[2-9],那么一共有 (高位+1)*cur所在位数(上例为10位) 的数带1,对上例来说,高位是23,cur所在位数是10位,那么一共有(23+1)*10=240个数里面带1。

还有一个问题,如果输入12,那么答案应该是5,因为1、10、11、12都包含1,11中包含两个1。那么上述分析能解决这个问题吗?

我们用230来分析:

  • cur在个位时,范围是001-221,有23个数包含1
  • cur在十位时,范围是010-219,有30个数包含1
  • cur在百位时,范围是100-199,有100个数包含1

cur在个位的范围中有11这个数,而cur在十位时,也有11这个数,这意味着11出现了两次,但上述的分析包含了这种情况,个位时有23个数包含1,十位时有30个数包含1,我们将他们相加就等于将11看成出现了两次。所以即便是一个数里有多个1,上面算法也能解决。

下面就开始写代码了,解析可以看开头贴出的大神原帖:

 int digit = 1;int res = 0, high = n / 10, cur = n % 10, low = 0;while (high != 0 || cur != 0) {if (cur == 0) res += high * digit;else if (cur == 1) res += high * digit + 1 + low;else res += (high+1) * digit;low += cur * digit;cur = high % 10;high /= 10;digit *= 10;}return res;

剑指offer43(leetcode 233),1-n整数中1出现的次数相关推荐

  1. 【LeetCode】剑指 Offer 43. 1~n 整数中 1 出现的次数

    [LeetCode]剑指 Offer 43. 1-n 整数中 1 出现的次数 文章目录 [LeetCode]剑指 Offer 43. 1-n 整数中 1 出现的次数 package offer;pub ...

  2. 剑指 Offer 43. 1~n 整数中 1 出现的次数(可能是最简洁易懂的)

    今天我们来看一道贼棒的题目,题目不长,很经典,也很容易理解,我们一起来看一哈吧, 大家也可能做过这道题,那就再复习一下,如果没做过的话,可以看完文章,自己去 AC 一下,不过写代码的时候,要自己完全写 ...

  3. 剑指 Offer 43. 1~n 整数中 1 出现的次数

    题目描述 输入一个整数 n ,求1-n这n个整数的十进制表示中1出现的次数. 例如,输入12,1-12这些整数中包含1 的数字有1.10.11和12,1一共出现了5次. 题解 循环判断每一个位为出现1 ...

  4. 剑指 Offer 43. 1~n整数中1出现的次数

    思路: 当一个数是七位数, xyzMabc 如果M == 0,由于M以前的数字可以取0~xyz-1,共计xyz个,而每一个后面带M的都有0~999,共计1000个 xyz*1000 如果M==1,由于 ...

  5. 剑指 Offer 43. 1~n 整数中 1 出现的次数(数位dp)

    思路:就是数位dp,dp[idx][sum][limit]代表,到idx位,前面有sum个0,有没有limit限制: class Solution { public:int dp[20][50][2] ...

  6. 剑指Offer - 面试题56 - I. 数组中数字出现的次数(异或,分组)

    1. 题目 一个整型数组 nums 里除两个数字之外,其他数字都出现了两次.请写程序找出这两个只出现一次的数字. 要求时间复杂度是O(n),空间复杂度是O(1). 示例 1: 输入:nums = [4 ...

  7. 剑指offer【43】:1-n中出现1的次数

    题目: 思路+代码: 法一:暴力法.遍历求和(超时) class Solution:def countDigitOne(self, n: int) -> int:# 暴力法超时if not n: ...

  8. java计算整数出现的次数_[剑指offer题解][Java]1到n整数中1出现的次数

    前言 众所周知,<剑指offer>是一本"好书". 如果你是个算法菜鸡(和我一样),那么最推荐的是先把剑指offer的题目搞明白. 对于剑指offer题解这个系列,我的 ...

  9. 【LeetCode】剑指 Offer 53 - I. 在排序数组中查找数字 I

    [LeetCode]剑指 Offer 53 - I. 在排序数组中查找数字 I 文章目录 [LeetCode]剑指 Offer 53 - I. 在排序数组中查找数字 I 一.二分法 总结 一.二分法 ...

最新文章

  1. FFMPEG H264/H265 编码延迟问题
  2. 浮点数正则表达式_正则表达式的邮箱,手机号,身份证号,密码
  3. 产品的三层境界:工具-平台-生态
  4. 内存位置访问无效_万字长文——java内存模型之volatile深入解读
  5. 读取TFrecord
  6. 科沃斯机器人阿尔法怎么样_科沃斯阿尔法扫地机器人,实用的才是最好的
  7. php中的active,用ActivePHP打造版本管理系统
  8. CSS经典书写技巧之(二)
  9. OpenStack 是什么
  10. 使用Java+MapReduce实现热词发现
  11. word文档单独删除或修改首页或某一页的页眉页脚及其下划线
  12. 怎么使用win10自带修复系统功能
  13. 哪里看最新行业研报?
  14. IDEA中Tomcat在控制台乱码问题以及IDEA编码设置UTF-8
  15. 程序复杂度之圈复杂度
  16. 计算机桌面属性打不开,电脑计算机属性打不开怎么办
  17. verilog练习:hdlbits网站上的做题笔记(7)!强烈推荐!
  18. vim如何提高效率:使用jk绑定Esc
  19. BZOJ2244: [SDOI2011]拦截导弹(CDQ分治,二维LIS,计数)
  20. 结合自定义注解,java反射和comparator实现对象的排序

热门文章

  1. python制作英语小词典_Python爬虫之自制英汉字典
  2. 利用gromacs软件绘制自由能形貌图
  3. 按下( )组合键 可以快速锁定计算机,锁定计算机,小编教你锁定计算机的快捷键...
  4. 胶类及胶性色素渍的去除方法
  5. SAP MM 发票预制 Function Module - BAPI_INCOMINGINVOICE_PARK
  6. html中加载rmvb,网页中播放RMVB格式的代码写法
  7. fedora 19 安装后优化
  8. dopdf——pdf生成工具
  9. 【转】SCI投稿经验
  10. [C++游戏示例]2048-程序员版