面试题32:从1到n整数中1出现的次数
这是一道广为流传的google面试题。用最直观的方法求解并不是很难,但遗憾的是效率不是很高;而要得出一个效率较高的算法,需要比较强的分析能力,并不是件很容易的事情。当然,google的面试题中简单的也没有几道。
硬上:O(nlogn)
int NumberOf1(unsigned int n); int NumberOf1Between1AndN_Solution1(unsigned int n)
{
int number = ; for(unsigned int i = ; i <= n; ++ i)
number += NumberOf1(i); return number;
} int NumberOf1(unsigned int n)
{
int number = ;
while(n)
{
if(n % == )
number ++; n = n / ;
} return number;
}
方法二:
我们用一个稍微大一点的数字21345作为例子来分析。我们把从1到21345的所有数字分成两段,即1-1235和1346-21345。
先来看1346-21345中1出现的次数。1的出现分为两种情况:一种情况是1出现在最高位(万位)。从1到21345的数字中,1出现在10000-19999这10000个数字的万位中,一共出现了10000(104)次;另外一种情况是1出现在除了最高位之外的其他位中。例子中1346-21345,这20000个数字中后面四位中1出现的次数是2000次(2*103,其中2的第一位的数值,103是因为数字的后四位数字其中一位为1,其余的三位数字可以在0到9这10个数字任意选择,由排列组合可以得出总次数是2*103)。
至于从1到1345的所有数字中1出现的次数,我们就可以用递归地求得了。这也是我们为什么要把1-21345分为1-1235和1346-21345两段的原因。因为把21345的最高位去掉就得到1345,便于我们采用递归的思路。
分析到这里还有一种特殊情况需要注意:前面我们举例子是最高位是一个比1大的数字,此时最高位1出现的次数104(对五位数而言)。但如果最高位是1呢?比如输入12345,从10000到12345这些数字中,1在万位出现的次数就不是104次,而是2346次了,也就是除去最高位数字之后剩下的数字再加上1。
int NumberOf1(const char* strN);
int PowerBase10(unsigned int n); int NumberOf1Between1AndN_Solution2(int n)
{
if(n <= )
return ; char strN[];
sprintf(strN, "%d", n); return NumberOf1(strN);
} int NumberOf1(const char* strN)
{
if(!strN || *strN < '' || *strN > '' || *strN == '\0')
return ; int first = *strN - '';
unsigned int length = static_cast<unsigned int>(strlen(strN)); if(length == && first == )
return ; if(length == && first > )
return ; // 假设strN是"21345"
// numFirstDigit是数字10000-19999的第一个位中1的数目
int numFirstDigit = ;
if(first > )
numFirstDigit = PowerBase10(length - );
else if(first == )
numFirstDigit = atoi(strN + ) + ; // numOtherDigits是01346-21345除了第一位之外的数位中1的数目
int numOtherDigits = first * (length - ) * PowerBase10(length - );
// numRecursive是1-1345中1的数目
int numRecursive = NumberOf1(strN + ); return numFirstDigit + numOtherDigits + numRecursive;
} int PowerBase10(unsigned int n)
{
int result = ;
for(unsigned int i = ; i < n; ++ i)
result *= ; return result;
}
面试题32:从1到n整数中1出现的次数的更多相关文章
- 剑指Offer:面试题32——从1到n整数中1出现的次数(java实现)
问题描述: 输入一个整数n,求1到n这n个整数的十进制表示中1出现的次数.例如输入12,从1到12这些整数中包含1的数字有1,10,11,12,1一共出现了5次. 思路:(不考虑时间效率的解法,肯定不 ...
- 【剑指Offer面试编程题】题目1373:整数中1出现的次数--九度OJ
题目描述: 亲们!!我们的外国友人YZ这几天总是睡不好,初中奥数里有一个题目一直困扰着他,特此他向JOBDU发来求助信,希望亲们能帮帮他.问题是:求出1~13的整数中1出现的次数,并算出100~130 ...
- 剑指Offer的学习笔记(C#篇)-- 整数中1出现的次数(从1到n整数中1出现的次数)
题目描述 求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1.10.11.12.13因此共出现6次,但是对于后面问题他就没辙了. ...
- 【剑指Offer】31、从1到n整数中1出现的次数
题目描述: 求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1.10.11.12.13因此共出现6次,但是对于后面问题他 ...
- 【剑指Offer面试题】 九度OJ1517:链表中倒数第k个结点
鲁棒性是指程序可以推断输入是否符合规范要求,并对不和要求的输入予以 合理的处理. 题目链接地址: http://ac.jobdu.com/problem.php?pid=1517 题目1517:链表中 ...
- 剑指offer——面试题32.1:分行从上到下打印二叉树
void BFSLayer(BinaryTreeNode* pRoot) { if(pRoot==nullptr) return; queue<BinaryTreeNode*> pNode ...
- 剑指offer——面试题32:从上到下打印二叉树
void BFS(BinaryTreeNode* pRoot) { if(pRoot==nullptr) { cout<<"empty binary tree!"< ...
- 【剑指offer 面试题38】数字在排序数组中出现的次数
思路: 利用二分查找,分别查找待统计数字的头和尾的下标,最后做差加一即为结果. C++: #include <iostream> #include <vector> using ...
- 剑指offer——面试题15.2:判断两个整数m和n的二进制中相差多少位
#include"iostream" using namespace std; int CountDifferentBit(int m,int n) { ,diff=m^n; wh ...
- 面试题32.从1到n整数中1出现的次数
题目:输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数.例如输入12,从 1到12这些整数中包含1的数字中1,10,11和12,1一共出现了5次 本题可以直接变量1到n的n个数然后分别计 ...
随机推荐
- 使用OpenCV进行标定(转载)
转载自牛猫靖 http://www.cnblogs.com/2008nmj/p/6278076.html 使用OpenCV进行相机标定 1. 使用OpenCV进行标定 相机已经有很长一段历史了.但是 ...
- Codeforces Round #405 (rated, Div. 2, based on VK Cup 2017 Round 1)A B C 水 并查集 思路
A. Bear and Big Brother time limit per test 1 second memory limit per test 256 megabytes input stand ...
- python---tornado补充(异步非阻塞)
一:正常访问(同一线程中多个请求是同步阻塞状态) import tornado.ioloop import tornado.web import tornado.websocket import da ...
- HDU 2827 高斯消元
模板的高斯消元.... /** @Date : 2017-09-26 18:05:03 * @FileName: HDU 2827 高斯消元.cpp * @Platform: Windows * @A ...
- 【BZOJ】1690: [Usaco2007 Dec]奶牛的旅行
[算法]01分数规划-最优比率环 [题意]给定有向图,点有收益,边有代价,重复经过的话收益不叠加而代价叠加,求从任意点开始最后回归该点的(收益/代价)最大. [题解] 和普通的分数规划不同,这里的方案 ...
- 【BZOJ 1001】[BJOI2006]狼抓兔子(最大流)
题目链接 最大流裸题,没什么好说吧,恰好点数多,考验网络流的效率,正好练\(Dinic\). #include <cstdio> #include <queue> #inclu ...
- NYOJ 138 找球号(二) (哈希)
题目链接 描述 在某一国度里流行着一种游戏.游戏规则为:现有一堆球中,每个球上都有一个整数编号i(0<=i<=100000000),编号可重复,还有一个空箱子,现在有两种动作:一种是&qu ...
- CSS Sprite笔记
1. 什么是CSS Sprite 将一些碎小的图片拼接为一张大点的图片来使用,目的是为了减少浏览器的http请求次数以提高网页的加载速度.每次请求图片都需要跟服务器建立一次连接,并且浏览器的最大并发请 ...
- BERT(Bidirectional Encoder Representations from Transformers)理解
BERT的新语言表示模型,它代表Transformer的双向编码器表示.与最近的其他语言表示模型不同,BERT旨在通过联合调节所有层中的上下文来预先训练深度双向表示.因此,预训练的BERT表示可以通过 ...
- struct msghdr和struct cmsghdr【转载】
理解struct msghdr当我第一次看到他时,他看上去似乎是一个需要创建的巨大的结构.但是不要怕.其结构定义如下:struct msghdr { void *msg_name ...