整数中1出现的次数(从1到n整数中1出现的次数)

题目描述

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

规律( 1 的数目)

如果第 i 位(自右向左,从1开始标号)上的数字是0,则第 i 位可能出现 1 的次数由更高位决定(若没有高位,则视高位为0),等于更高位数乘以当前位数的权重(10i-1)

如果第 i 位上的数字为 1,则第 i 位上出现 1 的次数不仅受更高位影响,还受低位影响(若没有低位,视低位为0),等于更高位数乘以当前位数的权重 (10i-1) + (低位数 + 1)

如果第 i 位上的数字大于 1,则第 i 位上可能出现 1 的次数仅由更高位决定(若没有高位,视高位为0),等于(更高位数 + 1)乘以当前位数的权重 (10i-1)

规律(x 的数目)

这里的 x 属于[1, 9], 因为 x = 0 不符合下列规律,需要单独计算

首先要知道以下规律

  • 从 1 至 10,在它们的个位数中,任意的 x 都出现了 1 次
  • 从 1 至 100,在它们的十位数中,任意的 x 都出现了 10 次
  • 从1至1000,在它们的百位数中,任意的x都出现了100次
  • 依次类推,从 1 至 10i,在它们的左数第二位(右数第 i 位),任意的 x 都出现了 (10i-1)次。这个规律很容易验证,这里不再多做说明

接下以 n = 2593, x = 5 为例来解释如何得到数学公式。从 1 至 2593中,数字 5 总计出现了 813 次,其中有 259次出现在个位,260次出现在十位,294次出现在百位,0次出现在千位

  • 现在依次分析这些数据,首先是个位。从 1 至 2590 中,包含了 259 个 10,因此任意的 x 都出现了 259 次。最后剩余的三个数 2531,2592,2593,因为它们最大的个位数字 3 < x。因此不会包含任何 5. (也可以这么看, 3 < x, 则个位上可能出现的 x 的位数由更高位决定,等于更高位数字 (259) * 101-1 = 259)。

  • 然后是十位。从 1 至 2500中,包含了25个100,因此任意的 x 都出现了 25 * 10 = 250 次。剩下的数字从 2501 至 2593,它们最大的十位数是 9 > x,因此会包含全部 10 个 5。最后总计 250 + 10 = 260。(也可以这么看,9 > x,则十位上可能出现的 x 的位数由更高位决定,等于更高位数字(25 + 1) * 102-1 = 260)

  • 接下来是百位。从1至2000中,包含了2个1000,因此任意x都出现了2 * 100 = 200次。剩下的数字从2001至2593,它们最大的百位数字5 == x,这时候情况就略微复杂,它们的百位肯定是包含5的,但是不会包含全部100个。如果把百位是5的列出来,是从2500至2593,数字的个数与十位和个位数字有关,是93 + 1 = 94。最后总计 200 + 94 = 294。(也可以这么看, 5 == x,则百位上可能出现的x次数不仅受跟高位影响,还受低位影响,等于更高位数字 2 * 103-1 + (93 + 1))

  • 最后是千位,现在已经没有更高位,因此直接看最大的千位数字 2 < x,因此不会包含任何 5 。(也可以这么看,2 < x,则千位上可能出现的x的次数仅由更高位决定,等于更高位数字 0 * 104-1 = 0)

到此为止,已经计算出全部数字 5 的出现次数。

总结

总结一下以上的算法,可以看到,当计算右数第 i 位包含的 x 的个数时:

  • 取第 i位左边(高位)的数字,乘以 10i-1,得到基础值 a

  • 取第 i 位数字,计算修正值

  • 如果大于 x , 则结果为 a + 10i-1

  • 如果小于 x,则结果为 a

  • 如果等于 x,则取第 i 位右边(低位)数字,设为 b,最后结果为 a + b + 1

代码

class Solution {
public:
int NumberOf1Between1AndN_Solution(int n)
{
if(n < 1) return 0;
if(n < 9) return 1; int high = 0;
int k = 0;
int cur = 0;
int count = 0; for(int i = 1; k = n / i; i *= 10){
high = k / 10; count += high * i; cur = k % 10;
if(cur > 1)
count += i;
else if(cur == 1)
count += n - k * i + 1;
} return count;
}
};

整数中1出现的次数(从1到n整数中1出现的次数)的更多相关文章

  1. 剑指Offer-31.整数中1出现的次数(从1到n整数中1出现的次数)(C++/Java)

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

  2. 31.整数中1出现的次数(从1到n整数中1出现的次数)

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

  3. php字符串查找函数 php查找字符串中出现的次数函数substr_count,判断字符串中是否包含另一个字符串函数strpos

    php字符串查找函数 php查找字符串中出现的次数函数substr_count,判断字符串中是否包含另一个字符串函数strpossubstr_count($haystack, $needle [,$o ...

  4. python1.返回一个字符串中出现次数第二多的单词 2.字符串中可能有英文单词、标点、空格 3.字符串中的英文字符全部是小写

    import re from collections import Counter def second_count_word(s): # # 利用正则按标点和空格切割,有其他标点可以添加到[]内 # ...

  5. 给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组

    题目描述: 给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组. 说明:初始化 nums1 和 nums2 的元素数量分别为 m ...

  6. LoadRunner中Action的迭代次数的设置和运行场景中设置

    LoadRunner中Action的迭代次数的设置和运行场景中设置 LoadRunner是怎么重复迭代和怎么增加并发运行的呢? 另外,在参数化时,对于一次压力测试中均只能用一次的资源应该怎么参数化呢? ...

  7. 对于大于等于3的整数n,在区间【n,3/2 * n】中一定存在一个素数

    对于大于3的整数n,在区间[n,3/2 * n]中一定存在一个素数

  8. 4.产生10个1-100的随机数,并放到一个数组中 (1)把数组中大于等于10的数字放到一个list集合中,并打印到控制台。 (2)把数组中的数字放到当前文件夹的numArr.txt文件中

    package cn.it.text; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayLis ...

  9. Python学习之---Python中的内置函数(方法)(更新中。。。)

    add(item)   #将item添加到s中,如果item已经在s中,则无任何效果 break        #退出循环,不会再运行循环中余下的代码 bool()     #将参数转换为布尔型 by ...

随机推荐

  1. 十四:Using CGroups with YARN

        Cgroups可以控制linux 上应用程序的资源(内存.CPU)使用,yarn可以使用Cgroups来CPU使用.Cgroups的配置,在yarn-site.xml中设置: 1)启用Cgro ...

  2. 十三:Transparent Encryption in HDFS(转)

    透明加密:http://blog.csdn.net/linlinv3/article/details/44963429 hadoop透明加密  kms 简介      Hadoop Key Manag ...

  3. POJ 2069 Super Star(计算几何の最小球包含+模拟退火)

    Description During a voyage of the starship Hakodate-maru (see Problem 1406), researchers found stra ...

  4. 环境变量PATH

    一.举例 我在用户主文件夹执行命令“ls”,会在屏幕显示该文件夹下的所有文件.然而,ls的完整文件名为“/bin/ls”,按道理我不在/bin下要想执行ls命令必须输入“/bin/ls”,但我仅仅需要 ...

  5. “Hello world!”团队—团队选题展示(视频展示说明)

    本次博客的主要内容基本分为以下两方面: 一.视频截图展示 二.视频简要说明 博客内容展示: 视频截图1: 简要说明:这是组长在视频前期简要介绍我们这款游戏项目的内容.从可行性和需求市场方面进行了简要阐 ...

  6. java多线程三之线程协作与通信实例

    多线程的难点主要就是多线程通信协作这一块了,前面笔记二中提到了常见的同步方法,这里主要是进行实例学习了,今天总结了一下3个实例: 1.银行存款与提款多线程实现,使用Lock锁和条件Condition. ...

  7. 计算器软件实现系列(七)WPF+SQL+策略模式

    一  整体概述 本次设计主要是在WPF的页面中实现的,属于表现层的更换,数据库部分用的还是数据库的封装,其中引用了策略模式 二  设计思路 1 在出题页面,进行试题的编辑,在编辑后会自动保存到数据库中 ...

  8. lintcode-42-最大子数组 II

    42-最大子数组 II 给定一个整数数组,找出两个 不重叠 子数组使得它们的和最大. 每个子数组的数字在数组中的位置应该是连续的. 返回最大的和. 注意事项 子数组最少包含一个数 样例 给出数组 [1 ...

  9. 读写INI文件操作类

    详情介绍:http://zh.wikipedia.org/wiki/INI%E6%96%87%E4%BB%B6 示例: 下面是一个虚拟的程序,其INI文件有两个小节,前面的小节是用来设置拥有者的信息, ...

  10. [Redis]在Windows下的下载及安装

    1.下载 下载地址: https://github.com/MSOpenTech/redis, 下载并解压到特定的目录. 2.启动Redis服务端 CMD -> redis-server.exe ...