题目描述

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

(题目意思是:输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数)

思路分析:

思路一:(不考虑时间效率的解法,靠它想拿offer有点难)

从1到n遍历求每个数字中1的个数,然后累加,每个数用求余运算(%),若余数为1,则说明该位为1。大多数人应该可以求解。

思路二:(从数字规律着手明显提高效率的做法,能让面试官耳目一新)

如果希望不用计算每个数字的1的个数,那就只能去寻找1在数字中出现的规律了。为了找到规律,我们不妨用一个稍微大一点的数字如21345作为例子来分析。我们把从1到21345分为两段,一段是从1到1345,另一段是从1346到21345。

我们先看从1346到21345中1出现的次数。1的出现分两种情况。首先分析1出现在最高位(本例中是万位)的情况。从1346到21345的数字中,1出现在10000到19999这10000个数字的万位中,一共出现了10000(10^4)个。

值得注意的是,并不是对所有5位数而言在万位出现的次数都是10000个。对于万位是1的数字比如输入12345,1只出现在10000到12345的万位,出现的次数不是10^4次,而是2346次,也就是除去最高数字位之后剩下的数字再加上1(即2345+1=2346)。

接下来分析1出现在除最高位之外的其他四位数中的情况。本例中1346到21345这2000个数字后四位中1出现的次数是8000次。由于最高位是2,我们可以再把1346到21345分为两段,1346到11345和11346到213456.每一段剩下的4位数字中,选择其中一位是1,其余三位可以在0~9这10个数字中任选,因此根据排序组合的原则,总共出现的次数是2*4*10^3=8000次。

至于1到1345中1出现的次数,我们就可以根据递归求得了。这也就是为什么把1~21345分为1~1345和1346~21345两段的原因。因为把21345的最高位去掉就变为1345,便于我们采用递归的思路。

参考代码如下:

#include <iostream>
#include <stdio.h>
using namespace std;class Solution {
public:/*方法1:int NumberOf1Between1AndN_Solution(int n){if(n<=0)return 0;int number=0;for(int i=1;i<=n;i++){int temp=i;while(temp)    //注意这里一定是用一个中间临时变量来存取每次读入的数字i{int s=temp%10;if(s==1)number++;temp=temp/10;}}return number;}*///方法2:int NumberOf1Between1AndN_Solution(int n){if (n <= 0)return 0;char strN[50];sprintf_s(strN, "%d", n);   //为了编程方便,将数字转换为字符串return NumberOf1(strN);}int powerBase10(int n){int result = 1;for (int i = 0; i<n; i++)result *= 10;return result;}int NumberOf1(char *strN){if (strN == NULL || *strN<'0' || *strN>'9' || *strN == '\0')return 0;int first = *strN - '0';int length = static_cast<int>(strlen(strN));if (length == 1 && first == 0)return 0;if (length == 1 && first>0)return 1;//假设strN是"21345"//numFirstDigit是数字10000~19999的第一位中的数目int numFirstDigits = 0;if (first>1)numFirstDigits = powerBase10(length - 1);else if (first == 1)numFirstDigits = atoi(strN + 1) + 1;   //atoi是把字符串转换成整型数的一个函数//numOtherDigits是1346~21345除了第一位之外的数位中的数目int numOtherDigits = first*(length - 1)*powerBase10(length - 2);int numRecursive = NumberOf1(strN + 1);return numFirstDigits + numOtherDigits + numRecursive;}
};int main()
{Solution s;int n;cin >> n;int CountOf1=s.NumberOf1Between1AndN_Solution(n);cout << CountOf1 << endl;system("pause");
}

剑指offer面试题[32]:从1到n整数中1出现的次数相关推荐

  1. 剑指offer 面试题32 从1到n整数中1出现的次数

    题目链接: 剑指offer啊 题目描述: 输入N, 求从1到n整数中1出现的次数 解题思路: 一开始的想法只能是暴力, 但是自己太蠢了啊, 看了看剑指offer上的做法就是巧妙的利用了递归...... ...

  2. 剑指offer——面试题32:从1到n整数中1出现的次数

    剑指offer--面试题32:从1到n整数中1出现的次数 Solution1: 最容易想到的方法: class Solution { public:int NumberOf1Between1AndN_ ...

  3. 剑指offer——面试题38:数字在排序数组中出现的次数

    剑指offer--面试题38:数字在排序数组中出现的次数 20180906整理 Solution1: [注意]先利用二分查找扎到一个值然后再顺序遍历的做法时间复杂度也是O(n)O(n)O(n),代码也 ...

  4. 二维数组的空间复杂度_剑指 offer 面试题精选图解 04 . 二维数组中的查找

    点击关注上方"图解面试算法", 设为"置顶或星标",一起刷 LeetCode. 作者:程序员吴师兄 今天分享的题目来源于 LeetCode 上的剑指 Offer ...

  5. 面试题32.从1到n整数中1出现的次数

    题目:输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数.例如输入12,从 1到12这些整数中包含1的数字中1,10,11和12,1一共出现了5次 本题可以直接变量1到n的n个数然后分别计 ...

  6. 剑指Offer - 面试题32 - III. 从上到下打印二叉树 III(BFS,queue+stack)

    1. 题目 请实现一个函数按照之字形顺序打印二叉树, 即第一行按照从左到右的顺序打印, 第二层按照从右到左的顺序打印, 第三行再按照从左到右的顺序打印,其他行以此类推. 例如: 给定二叉树: [3,9 ...

  7. 剑指Offer - 面试题32 - I. 从上到下打印二叉树(按层BFS遍历,queue)

    1. 题目 从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印. 例如: 给定二叉树: [3,9,20,null,null,15,7],3/ \9 20/ \15 7 返回: [3,9 ...

  8. 剑指offer面试题32 - III. 从上到下打印二叉树 III(二叉树)(BFS)

    题目描述 请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推. 思路 详见链接 代码 class So ...

  9. 剑指offer面试题32 - I. 从上到下打印二叉树(二叉树)(BFS)

    题目描述 从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印. 思路 详见链接 代码 class Solution:def levelOrder(self, root:TreeNode ...

最新文章

  1. 写缓冲器 + 无效队列,优化MESI协议的性能
  2. 动态生成能够局部刷新的验证码【AJAX技术】---看了不懂赔你钱
  3. New Companies(关联查询+group by)
  4. python 父类构造函数,python 对于子类构造函数重写父类构造函数的了解
  5. servlet实现文件上传,预览,下载和删除
  6. Entity Framework Core 2.1带来更好的SQL语句生成方案
  7. 判断一个图中有无环路的存在
  8. 【数字图像处理】Canny边缘检测详解及编程实现
  9. 酒店管理系统软件服务器端,酒店管理系统erp
  10. Alibaba之EasyExcel使用
  11. AAAI2021联邦学习论文集
  12. 高数 | 一点可导和邻域内可导能推出来什么?
  13. 力科(Lecroy)示波器专用波形文件(轨迹文件/trace文件/.trc文件)在MATLAB上的解析与回写
  14. 有哪些好的编程习惯从一开始就值得坚持?
  15. GEO-BYB型振弦式表面应变计的主要作用
  16. sql server 简单应用
  17. 异常:egret获取引擎列表失败
  18. 桌面端如何运行小程序?
  19. 鸡蛋的吃法及营养价值
  20. Oracle ltrim() 函数详细用法

热门文章

  1. function adapter bind(C++11)
  2. Python爬虫都被你用来爬妹子图了,我等羞愧与之为伍!
  3. 注塑机摆放间距多少合适_垃圾分类盛行,生产塑料环卫垃圾桶的注塑机怎么选?...
  4. 华为手机全面鸿蒙,彻底与安卓说拜拜,华为手机全面鸿蒙时代即将到来
  5. kotlin t class.java_尝试Java,从入门到Kotlin(下)
  6. 普罗米修斯监控linux,Prometheus(普罗米修斯)搭建监控
  7. 安卓10未知来源_华为已将“基于安卓10”变成“兼容安卓10”,EMUI就是鸿蒙OS
  8. 基于机器视觉的玻璃Mark点字符识别
  9. 201700071045.md
  10. 洛谷P1079 Vigenère 密码