参考: 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. windows使用docker运行mysql等工具(一)windows安装docker

    由于我本地的mysql版本比较低,最近想着要升级一下mysql版本,鉴于docker容器的火热,就想着在本地装个docker环境,然后下载最新版的mysql镜像,完成mysql8.0的安装.电脑是wi ...

  2. UiPath之数据透视表

    今天给各位小伙伴们讲讲如何使用UiPath来创建数据透视表,相信大家在Execl中经常会使用. ---小U的QQ群(714733686):小U的订阅号[UiPath8888]--- 在UiPath里面 ...

  3. python关于urllib库与requests

    对于这两个库来说个人推荐使用requests库 下面用实例来说明 urllib库: requests库: 实现同样功能: 实现同样的功能下urllib比request步骤更复杂,这个对于我们编程来说是 ...

  4. 瞎折腾实录:构建 Armel 版本的 .NET Core 教程和资料资源

    目录 首先我要说明,我失败了~ 我把我的进度和经验放出来,希望能够帮助别人完成编译工作~ 背景:最近接手一个华为某型号的嵌入式设备,需要在上面搭建 .NET Core 环境. 设备是 Armel 架构 ...

  5. 2019年PHP面试题附答案(实战经验)

    出于一些原因近期做了一次工作变动,在职交接近一个半月时间大概面试了十五家公司,并且得到了自己比较满意的offer,最后基本上无缝衔接了新工作.总体来说,虽然准备的很充分,但面试期间还是暴露了许多问题, ...

  6. [LC]876题 Middle of the Linked List (链表的中间结点)(链表)

    ①中文题目 给定一个带有头结点 head 的非空单链表,返回链表的中间结点. 如果有两个中间结点,则返回第二个中间结点. 示例 1: 输入:[1,2,3,4,5]输出:此列表中的结点 3 (序列化形式 ...

  7. spark安装配置

    一.下载解压 二.配置 (假设已经配置了Java.Hadoop) 1.环境变量 2.spark配置 进入spark安装目录,复制文件 编辑spark-env.sh文件,在文件中添加如下信息(括号中路径 ...

  8. hdu 1530 Maximum Clique (最大包)

    Maximum CliqueTime Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)T ...

  9. ACL2019: 《GraphRel: Modeling Text as Relational Graphs for Joint Entity and Relation Extraction》源码解析

    论文地址:<GraphRel: Modeling Text as Relational Graphs for Joint Entity and Relation Extraction> G ...

  10. 快速遍历OpenCV Mat图像数据的多种方法和性能分析 | opencv mat for loop

    本文首发于个人博客https://kezunlin.me/post/61d55ab4/,欢迎阅读! opencv mat for loop Series Part 1: compile opencv ...