参考: 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. 11、pytest -- 测试的参数化

    目录 1. @pytest.mark.parametrize标记 1.1. empty_parameter_set_mark选项 1.2. 多个标记组合 1.3. 标记测试模块 2. pytest_g ...

  2. MySQL传统点位复制在线转为GTID模式复制

    1.  GTID优缺点 MySQL传统点位复制在5.7版本前是主要的主从复制模式,而随着MySQL5.6版本引入GTID,并且MySQL5.7进行各方面的优化以后,在mySQL5.7(尤其是MySQL ...

  3. 雅虎日本如何用 Pulsar 构建日均千亿的消息平台

    雅虎日本是一家雅虎和软银合资的日本互联网公司,是日本最受欢迎的门户网站之一.雅虎日本的互联网服务在日本市场占主导地位. 下图从三个维度显示了雅虎日本的经营规模.第一个是服务数量,雅虎日本提供上百种互联 ...

  4. UEFI+GPT电脑Win10下安装openSUSE Leap 42.2双系统

    安装过程仅供参考,最后实现方式不完美. 1       准备工具,一个8G以上U盘,已装好win10的UEFI+GPT电脑(本机为SSD+HDD双硬盘) 2       所需软件: 2.1       ...

  5. Linux菜鸟——常见命令一 权限

    Linux对文件和目录的权限位 权限位是十位 第一位 代表文件类型 - 普通文件 d 目录文件 l 链接文件 后面九尾 所有者权限 u = user 所属组权限 g = group 其他人权限 o = ...

  6. python_day05

    今日内容 ''' post请求登录github Request URL: https://github.com/session Request Method: POST #Referer表示上一个请求 ...

  7. python脚本编写(纯干货)

    写博客的经验不是很多,写的不好或者有什么建议请留言或者联系作者 文章所有权归作者所有,转载转发请联系作者,侵权必纠. 废话不多说,直接开始吧! python脚本的作用也就不说了,首先是一个reques ...

  8. 达梦"记录超长"警告

    出现"记录超长"背景介绍: 导入数据库时,出现数据库记录超长警告,导致数据无法正常导入! 1.重新建库,把页大小改大 这种方式是在建立数据库实例的时候进行的 修改[页大小] 2.把 ...

  9. ceph中rbd的增量备份和恢复

    ceph中rbd的增量备份和恢复 ceph的文档地址:Ceph Documentation ​ 在调研OpenStack中虚机的备份和恢复时,发现OpenStack和ceph紧密结合,使用ceph做O ...

  10. numpy和matplotlib下载中出现的问题

    在安装numpy的时候遇到如下所示的错误: 经过几个小时的查找,最终发现是pygame的路径不对导致.将pygame的具体路径加上后,问题解决.实施如下:得出一个结论:路径很重要,千万得小心哦. 报错 ...