参考: https://troywu0.gitbooks.io/interview/整数中出现1的次数(从1到n整数中1出现的次数).html

题目描述

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

解题思路1 (暴力法,时间复杂度: O(nlog(n))

 public int NumberOf1Between1AndN_Solution(int n) {
     int count = 0;
     while (n > 0) {
         String nStr = String.valueOf(n);
         for (int i = 0; i < nStr.length(); i++) {
             if (nStr.charAt(i) == '1')
                 count++;
         }
         n--;
     }
     return count;
 }

这种方法的思路简单,统计每一个数中出现1的次数,能够快速写出代码。但是,这种方法的时间复杂度很高,O(nlog(n)),面试这么写,估计不会留下好的印象。

解题思路2 (数学规律法,时间复杂度: O(log(n))

 public int NumberOf1Between1AndN_Solution(int n) {
     int low = 0, cur = 0, high = 0;
     int count = 0;
     int factor = 1;
     while (factor <= n) {
         high = n / (factor * 10);
         low = n % factor;
 //            cur = (n - high * (factor * 10) - low) / factor;
         cur = (n / factor) % 10;
         if (cur == 0)
             count += high * factor;
         else if (cur == 1)
             count += high * factor + low + 1;
         else
             count += (high + 1) * factor;
         factor *= 10;
     }
     return count;
 }

这一个思路利用了数字的规律和特点,解决问题的效率非常的高,时间复杂度只与数的位数有关。

首先看一个规律:

  • 从1 - 10中,个位中 1 出现的次数是1,即1这个数;
  • 从1 - 100中,十位中 1 出现的次数是10, 即10, 11, ..., 18, 19;
  • 从1 - 1000中,百位中 1 出现的次数是100,即100, 101, ..., 198, 199;
  • 以此类推。

假设有一个四位数,使用 cur 来表示当前位数对应的数值,high表述cur左边的数,low表示cur右边的数。会有三种情况产生:

  • 第一种:cur = 0,1出现的次数等于 high * (该位数对应的基数)

    • 假设四位数为1023,求百位上1出现的次数;
    • 此时 high = 1, cur = 0, low = 23;
    • 次数 = 1 * 100;
    • 即100, 101, ..., 198, 199。
  • 第二种:cur = 1,1出现的次数等于 high * (该位数对应的基数) + low + 1

    • 假设四位数为1123,求百位上1出现的次数;
    • 此时 high = 1, cur = 1, low = 23;
    • 次数 = 1 * 100 + 23 + 1;
    • 即100, 101, ..., 198, 199  +  1100, 1101, ..., 1122, 1123。
  • 第三种:cur > 1,1出现的次数等于 (high + 1) * (该位数对应的基数)
    • 假设四位数为1223,求百位上1出现的次数;
    • 此时 high = 1, cur = 2, low = 23;
    • 次数 = (1 + 1) * 100;
    • 即100, 101, ..., 198, 199  + 1100, 1101, ..., 1198, 1199。

根据这一规律,从最低位至最高位,依次求出1出现的次数,最后相加得到最终的结果。

剑指offer-31:整数中1出现的次数(从1到n整数中1出现的次数)的更多相关文章

  1. 剑指 Offer 31. 栈的压入、弹出序列 + 入栈顺序和出栈顺序的匹配问题

    剑指 Offer 31. 栈的压入.弹出序列 Offer_31 题目详情: 解析: 这里需要使用一个栈来模仿入栈操作. package com.walegarrett.offer; /** * @Au ...

  2. 剑指 Offer 31. 栈的压入、弹出序列

    剑指 Offer 31. 栈的压入.弹出序列 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如,序列 {1,2,3,4,5} 是某 ...

  3. 【强烈推荐】《剑指Offer:名企面试官精讲典型编程题》一书中IT名企经典面试题

    各位程序猿:         <剑指Offer>一书源自该书作者何海涛坚持更新与编写的博客(http://zhedahht.blog.163.com/),该博客收集整理了大量如微软.Goo ...

  4. 【Java】 剑指offer(31) 栈的压入、弹出序列

    本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否 ...

  5. 【剑指Offer面试编程题】题目1508:把字符串转换成整数--九度OJ

    题目描述: 将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数. 输入: 输入可能包含多个测试样例. 对于每个测试案例,输入为一个合法或者非法的字符串,代表一个整数n(1<= n&l ...

  6. 剑指Offer 31. 整数中1出现的次数(从1到n整数中1出现的次数) (其他)

    题目描述 求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1.10.11.12.13因此共出现6次,但是对于后面问题他就没辙了. ...

  7. 剑指offer第12题打印从1到n位数以及大整数加法乘法

       字符和数字加减就是字符的ASCII码和数字直接加减. 方法一: 1)在字符串操作中给一个整形数字加(字符0)就是把它转化为字符,当然给一个字符减去(字符0)就可以把它转化为数字了:如果确实是最后 ...

  8. [剑指Offer] 31.整数中1出现的次数

    题目描述 求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1.10.11.12.13因此共出现6次,但是对于后面问题他就没辙了. ...

  9. 剑指offer——31序列化二叉树

    题目描述 请实现两个函数,分别用来序列化和反序列化二叉树   二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存.序列化可以基于先 ...

  10. 每日一题 - 剑指 Offer 31. 栈的压入、弹出序列

    题目信息 时间: 2019-06-25 题目链接:Leetcode tag:栈 难易程度:中等 题目描述: 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序.假设压入 ...

随机推荐

  1. Linux系统重启Oracle-12c步骤

    Linux系统重启Oracle-12c步骤 1. 使用oracle用户登录: [root@Oracle-12c /]# su – oracle 2. 登录oracle登陆管理员账号: [oracle@ ...

  2. redis 数据库主从不一致问题解决方案

     在聊数据库与缓存一致性问题之前,先聊聊数据库主库与从库的一致性问题. 问:常见的数据库集群架构如何? 答:一主多从,主从同步,读写分离. 如上图: (1)一个主库提供写服务 (2)多个从库提供读服务 ...

  3. jsp页面不乱码,外部引用的js弹出对话框乱码

    今天在做一个课程设计的时候,写到一个界面注册,在用js判断数据的正确性时,碰到了一个js弹出框的乱码问题.在网上找寻了很久,也找了很多博客看,但是发现怎么样都不能解决我的问题,下面给出几个比较经典的解 ...

  4. 7月22 Linux作业-文件管理

    习题内容 解答 1.答案 [root@centos7 ~]# echo '*/1 * * * * /usr/bin/cp /etc /data/`/usr/bin/date +\%Y-\%m-\%d` ...

  5. 从EFCore上下文的使用到深入剖析DI的生命周期最后实现自动属性注入

    故事背景 最近在把自己的一个老项目从Framework迁移到.Net Core 3.0,数据访问这块选择的是EFCore+Mysql.使用EF的话不可避免要和DbContext打交道,在Core中的常 ...

  6. T-SQL, Part II: IMAGE/TEXT Insert

    To insert data to IMAGE/TEXT (both keywords are recommend to replace with nvarbinary(MAX)/nvarchar(M ...

  7. 创建和销毁对象——用私有构造器或者枚举类型强化Singleton属性

    参考资料:<Effective Java>.<Java核心技术 卷1>.https://www.cnblogs.com/zhaosq/p/10135362.html 基础回顾 ...

  8. 【译】利用Lombok消除重复代码

    当你在写Getter和Setter时,一定无数次的想过,为什么会有POJO这么烂的东西.你不是一个人!(不是骂人-)无数的开发人员花费了大量的时间来写这种样板代码,而他们本来可以利用这些时间做出更有价 ...

  9. 一 linuk系统简介

    开源软件 使用的自由,绝大多数开源软件免费 研究的自由,可以获得软件源代码 散播及改良的自由,可以自由传播 改良甚至销售 linuk应用领域 基于linuk的企业服务器 扫描踩点网站www.netcr ...

  10. Python第五天 列表练习 元组类型 字典类型 小购物车练习

    # 反转 reverse# l=['lili','asdf','qwer','80000']# l.reverse()# print(l) # ['80000', 'qwer', 'asdf', 'l ...