面试题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个数然后分别计 ...
随机推荐
- 《剑指offer》— JavaScript(13)调整数组顺序使奇数位于偶数前面
调整数组顺序使奇数位于偶数前面 题目描述 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的 ...
- iOS之富文本(二)
之前做项目时遇到一个问题: 使用UITextView显示一段电影的简介,由于字数比较多,所以字体设置的很小,行间距和段间距也很小,一大段文字挤在一起看起来很别扭,想要把行间距调大,结 ...
- 2016-2017 ACM-ICPC East Central North America Regional Contest (ECNA 2016) F 区间dp
Problem F Removal GameBobby Roberts is totally bored in his algorithms class, so he’s developed a li ...
- 题解【bzoj2440 [中山市选2011]完全平方数】
Description 求第 \(k\) 个不含平方因子的正整数.多组询问.\(k \leq 10^9, T \leq 50\) Solution 网上的题解几乎都是容斥,这里给一个简单的也挺快的做法 ...
- 再谈System.arraycopy和Arrays.copyOf
之前转载过一篇博文,介绍过这两个方法,今天想要再次详细的了解一下. public static native void arraycopy(Object src, int srcPos, Object ...
- 前端PHP入门-025-数组-重中之重
数组是PHP中一个 很很很很很很很很很很重要 的一个 数据类型 . 学习数组,大家主要学习两部份的知识: 1.数组的定义,定义中的一些注意的坑 2.数组的函数使用 认识数组 数组定义 数组在之前我们让 ...
- Restful 接口传递参数
首先补充一下什么是 Restful ,这里简单说一下,如果一个架构符合REST原则,就称它为RESTful架构. RESTful架构特点: (1)每一个URI代表一种资源: (2)客户端和服务器之间, ...
- Order By 问题集合
问题(一):Order By 多个参数排序 在做多字段的排序的时候我们经常会会用到该语句. 所以多参数排序是从左到右的局部排序,修改的范围只有前面参数(几个参数)相同的情况下在排序. select * ...
- HDU 1211 EXGCD
EXGCD的模板水题 RSA算法给你两个大素数p,q定义n=pq,F(n)=(p-1)(q-1) 找一个数e 使得(e⊥F(n)) 实际题目会给你e,p,q计算d,$de \mod F(n) = 1$ ...
- 为什么 .NET 会被叫做 .NET?
微软开发.NET Framework是在20世纪90年代后期,最初是叫做“下一代Windows服务”(Next Generation Windows Services 简称 NGWS). 那么为什么微 ...