目录

1.数字1出现的次数

2.数字2出现的次数


1.数字1出现的次数

首先我们来看1到n中1次数的次数

对应letecode链接:

https://leetcode-cn.com/problems/1nzheng-shu-zhong-1chu-xian-de-ci-shu-lcof/

题目描述:

输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。

例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。

示例 1:

输入:n = 12
输出:5
示例 2:

输入:n = 13
输出:6

限制:

1 <= n < 2^31
注意:本题与主站 233 题相同:https://leetcode-cn.com/problems/number-of-digit-one/

解题思路:

太喜欢这种简洁的题目啦,言简意赅,就是让咱们找出小于等于 n 的非负整数中数字 1 出现的个数。大家看到这个题目的第一印象,可能会这样想,哦,让我们求 1 的个数。

呐我们直接逐位遍历每个数的每一位,当遇到 1 的时候,计数器 +1,不就行了。嗯,很棒的方法,可惜会超时。(我试了)。

或者说,我们可以先将所有数字拼接起来,然后再逐位遍历,这样仍会超时。(我也试了)

大家再思考一下还有没有别的方法呢?

既然题目让我们统计小于等于 n 的非负整数中数字 1 出现的个数。

那我们可以不可这样统计。

我们假设 n = abcd,某个四位数。

那我们完全可以统计每一位上 1 出现的次数,个数上 1 出现的次数,十位上 1 出现的次数,百位 ,千位。。。

也就是说小于等于 n 的所有数字中,个位上出现 1 的次数 + 十位出现 1 的次数 + 。。。最后得到的就是总的出现次数。

见下图

我们假设 n = 13 (用个小点的数,比较容易举例)。

我们需要统计小于等于 13 的数中,出现 1 的次数,

通过上图可知,个位上 1 出现 2 次,十位上 1 出现 4 次

那么总次数为 2 + 4 = 6 次。

另外我们发现 11 这个数,会被统计 2 次,它的十位和个位都为 1 ,

而我们这个题目是要统计 1 出现的次数,而不是统计包含 1 的整数,所以上诉方法不会出现重复统计的情况。

我们题目已经有大概思路啦,下面的难点就是如何统计每一位中 1 出现的次数呢?

我们完全可以通过遍历 n 的每一位来得到总个数,见下图

假设我们想要得到十位上 1 出现的次数,当前我们指针指向十位,

我们称之为当前位。num 则代表当前位的位因子,当前位为个位时 num = 1,十位时为 10,百位时为 100....

那我们将当前位左边的定义为高位,当前位右边的定义位低位。

例:n = 1004 ,此时指针指向十位(当前位)num = 10,高位为百位,千位,低位为个位

而且我们某一位的取值范围为 0 ~ 9,那么我们可以将这 10 个数分为 3 类,小于 1 (当前位数字为 0 ),等于 1(当前位数字为 1 ) ,大于 1(当前位上数字为 2 ~ 9),下面我们就来分别考虑三种情况。

我们进行举例的 n 为 1004,1014,1024。重点讨论十位上 3 种不同情况。大家阅读下方文字之前,先想象自己脑子里有一个行李箱的滚轮密码锁,我们固定其中的某一位,然后可以随意滑动其他位,这样可以帮助大家理解。

n = 1004
我们想要计算出小于等于 1004 的非负整数中,十位上出现 1 的次数。

也就是当前位为十位,数字为 0 时,十位上出现 1 的次数。

解析:为什么我们可以直接通过高位数字 * num,得到 1 出现的次数

因为我们高位为 10,可变范围为 0 ~ 10,但是我们的十位为 0 ,所以高位为 10 的情况取不到,所以共有 10 种情况。

又当前位为十位,低位共有 1 位,可选范围为 0 ~ 9 共有 10 种情况,所以直接可以通过 10 * 10 得到。

其实不难理解,我们可以设想成行李箱的密码盘,在一定范围内,也就是上面的 0010 ~ 0919 , 固定住一位为 1 ,只能移动其他位,看共有多少种组合。

好啦,这个情况我们已经搞明白啦,下面我们看另一种情况。

n = 1014
我们想要计算出小于等于 1014 的非负整数中,十位上出现 1 的次数。

也就是当前位为十位,数字为 1 时,十位上出现 1 的次数。

我们在小于 1014 的非负整数中,十位上为 1 的最小数字为 10,最大数字为 1014,所以我们需要在 10 ~ 1014 这个范围内固定住十位上的 1 ,移动其他位。

其实然后我们可以将 1014 看成是 1004 + 10 = 1014

则可以将 10 ~ 1014 拆分为两部分 0010 ~ 0919 (小于 1004 ),1010 ~ 1014。

见下图:

解析:为什么我们可以直接通过 高位数字 * num + 低位数字 + 1 即 10 * 10 + 4 + 1

得到 1 出现的次数

高位数字 * num 是得到第一段的次数,第二段为 低位数字 + 1,求第二段时我们高位数字和当前位已经固定,

我们可以改变的只有低位。

可以继续想到密码盘,求第二段时,把前 3 位固定,只能改变最后一位。最后一位最大能到 4 ,那么共有几种情况?

n = 1024
我们想要计算出小于等于 1024 的非负整数中,十位上出现 1 的次数。

也就是当前位为十位,数字为 2 ~ 9 时,十位上出现 1 的次数。其中最小的为 0010,最大的为 1019

我们也可以将其拆成两段 0010 ~ 0919,1010 ~ 1019

解析:为什么我们可以直接通过高位数字 * num + num, 10 * 10 + 10 得到 1 出现的次数

第一段和之前所说一样,第二段的次数,我们此时已经固定了高位和当前位,当前位为 1,低位可以随意取值,上诉例子中,当前位为 10,低位为位数为 1,则可以取值 0 ~ 9 的任何数,则共有 10 (num) 种可能。

在这里我们可以得出1~n中x出现的规律当然x不能是0.

对应代码:

int digitCounts(int k, int n) {//k代表xlong digit = 1;//相等与num先从各位开始算int res = 0, high = n / 10, low = 0, cur = n % 10;//res表示结果//high表示高位//low表示低位//cur表示当前位while (high || (cur)) {//直到高位为0并且当前位为0if (cur < k) res += high * digit;else if (cur == k) res += (high) * digit + low + 1;else res += (high + 1) * digit;low += cur * digit;//重新计算低位cur = high % 10;//当前位high /= 10;digit *= 10;//每次乘以十}return res;//返回结果}

下面我们给出letecode这题的题解:

class Solution {
public:int countDigitOne(int n) {return digitCounts(1,n);}int digitCounts(int k, int n) {//k代表xlong digit = 1;//相等与num先从各位开始算int res = 0, high = n / 10, low = 0, cur = n % 10;//res表示结果//high表示高位//low表示低位//cur表示当前位while (high || (cur)) {//直到高位为0并且当前位为0if (cur < k) res += high * digit;//小于kelse if (cur == k) res += (high) * digit + low + 1;else res += (high + 1) * digit;//相当于大于klow += cur * digit;//重新计算低位cur = high % 10;//当前位high /= 10;digit *= 10;//每次乘以十}return res;//返回结果}};

2.数字2出现的次数

对应letecode链接:

https://leetcode-cn.com/problems/number-of-2s-in-range-lcci/

题目描述:

编写一个方法,计算从 0 到 n (含 n) 中数字 2 出现的次数。

示例:

输入: 25
输出: 9
解释: (2, 12, 20, 21, 22, 23, 24, 25)(注意 22 应该算作两次)
提示:

n <= 10^9。

思路已在上面说过在这里给出代码:

class Solution {
public:int numberOf2sInRange(int n) {return digitCounts(2,n);}int digitCounts(int k, int n) {//k代表xlong digit = 1;//相等与num先从各位开始算int res = 0, high = n / 10, low = 0, cur = n % 10;//res表示结果//high表示高位//low表示低位//cur表示当前位while (high || (cur)) {//直到高位为0并且当前位为0if (cur < k) res += high * digit;else if (cur == k) res += (high) * digit + low + 1;else res += (high + 1) * digit;//大于klow += cur * digit;//重新计算低位cur = high % 10;//当前位high /= 10;digit *= 10;//每次乘以十}return res;//返回结果}
};

1到n中x出现的次数一类题(一网打尽)相关推荐

  1. 【leetcode】43.1~n整数中1出现的次数

    [题目]1-n整数中1出现的次数 原题链接 输入一个整数 n ,求1-n这n个整数的十进制表示中1出现的次数. 例如,输入12,1-12这些整数中包含1 的数字有1.10.11和12,1一共出现了5次 ...

  2. 求一个字符串中连续出现的次数最多的子串

    求一个字符串中连续出现的次数最多的子串.例如字符串"abababc",最多连续出现的为ab,连续出现三次.要和求一个字符串中的最长重复子串区分开来,还是上面的字符串,那么最长的重复 ...

  3. shell最大出现和连续出现次数_从 1 到 n 整数中 1 出现的次数

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

  4. 剑指offer:整数中1出现的次数(从1到n整数中1出现的次数)

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

  5. 【刷算法】整数中1出现的次数(从1到n整数中1出现的次数)

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

  6. java 循环list 对象_java计算list集合中重复对象的次数及for循环内外创建对象

    我的需求:计算字符串集合中"数值"出现的次数,然后在for循环中计算"数值"及出现的次数 解决方案: 1.使用collections类中的frequency(集 ...

  7. C++求从1到n的正整数中1出现的次数

    编程之美中的一道题: 题目:输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数. 例如输入12,从1到12这些整数中包含1 的数字有1,10,11和12,1一共出现了5次. 问题描述:给定 ...

  8. 【剑指offer-Java版】32从1到n的整数中1出现的次数

    1到n中1出现的次数: 书上的讲解实在是没看懂,翻翻作者的博客找到了一个通俗解法,自己又补充了一些思考细节,全在注释里面了 public class _Q32<T> {public sta ...

  9. python从1到n出现了多少个1-Python解决 从1到n整数中1出现的次数

    最近在看<剑指Offer>,面试题32的题目:输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数.例如输入12,从1到12这些整数中包含1的数字有1.10.11和12,1一共出 ...

最新文章

  1. PYTHON编程导论群问题汇总(五)
  2. Jsoup:使用Java将爬虫得到的数据写入Excel,Jsoup得到的数据进行持久化,爬虫数据保存到本地Excel中
  3. 【漏洞实战】某网站JS文件泄露导致拿到服务器权限
  4. SAP Cloud Platform上Destination属性为odata_gen的具体用途
  5. jdk、cglib动态代理代码示例
  6. SpringMVC_Controller注解与RequestMapping
  7. Android闹钟程序周期循环提醒源码(AlarmManager)【转】
  8. Linux 命令(107)—— systemctl 命令
  9. DbEntry 访问Access2010数据库
  10. Objective-C中的属性机制
  11. 【日常小问题3】win10电脑忘记开机密码的解锁方法【转载】
  12. 高频小信号谐振放大器的matlab仿真,高频小信号谐振放大器的MATLAB仿真
  13. FFmpeg 以及帧率的解释
  14. php获取openid提示错误40163,微信网页授权 40163 code已被使用过
  15. java 计算天数差_java中计算两个日期之间差的天数
  16. 我来告诉你,一个草根程序员如何逆袭,成功进入BAT!
  17. 计算机硬盘启动设置方法,如何在BIOS中设置硬盘启动
  18. php orc 验证码,百度图片识别orc实现普通验证码识别
  19. 手把手撸一个小而美的日历组件
  20. 设计简约风格节约用水公益海报的PS教程

热门文章

  1. 微信小程序真机调试和开发工具调试问题解决
  2. Ubuntu18.4安装vim报错解决
  3. [附源码]Python计算机毕业设计SSM旅游出行系统(程序+LW)
  4. 根据经纬度求1:1万的新图幅号(python3)
  5. 大众mpv_买别克GL8请等一等,大众商务MPV要来了长超5.3米,或售30万起
  6. 怎么判断自己面试是不是凉了?
  7. arduino智能浇花系统_解放双手!自己动手做一个简易智能浇花系统
  8. 计算机网络层协议介绍icmp/arp
  9. C语言结构体之输入学生基本信息
  10. 直播解决方案/sdk的选择