这是一道广为流传的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出现的次数的更多相关文章

  1. 剑指Offer:面试题32——从1到n整数中1出现的次数(java实现)

    问题描述: 输入一个整数n,求1到n这n个整数的十进制表示中1出现的次数.例如输入12,从1到12这些整数中包含1的数字有1,10,11,12,1一共出现了5次. 思路:(不考虑时间效率的解法,肯定不 ...

  2. 【剑指Offer面试编程题】题目1373:整数中1出现的次数--九度OJ

    题目描述: 亲们!!我们的外国友人YZ这几天总是睡不好,初中奥数里有一个题目一直困扰着他,特此他向JOBDU发来求助信,希望亲们能帮帮他.问题是:求出1~13的整数中1出现的次数,并算出100~130 ...

  3. 剑指Offer的学习笔记(C#篇)-- 整数中1出现的次数(从1到n整数中1出现的次数)

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

  4. 【剑指Offer】31、从1到n整数中1出现的次数

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

  5. 【剑指Offer面试题】 九度OJ1517:链表中倒数第k个结点

    鲁棒性是指程序可以推断输入是否符合规范要求,并对不和要求的输入予以 合理的处理. 题目链接地址: http://ac.jobdu.com/problem.php?pid=1517 题目1517:链表中 ...

  6. 剑指offer——面试题32.1:分行从上到下打印二叉树

    void BFSLayer(BinaryTreeNode* pRoot) { if(pRoot==nullptr) return; queue<BinaryTreeNode*> pNode ...

  7. 剑指offer——面试题32:从上到下打印二叉树

    void BFS(BinaryTreeNode* pRoot) { if(pRoot==nullptr) { cout<<"empty binary tree!"< ...

  8. 【剑指offer 面试题38】数字在排序数组中出现的次数

    思路: 利用二分查找,分别查找待统计数字的头和尾的下标,最后做差加一即为结果. C++: #include <iostream> #include <vector> using ...

  9. 剑指offer——面试题15.2:判断两个整数m和n的二进制中相差多少位

    #include"iostream" using namespace std; int CountDifferentBit(int m,int n) { ,diff=m^n; wh ...

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

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

随机推荐

  1. git分支管理图

  2. Python学习笔记(三十一)正则表达式

    ---恢复内容开始--- 摘抄自:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000 ...

  3. Delphi 常用数据类型 字符串类型 数据类型等等

    字符串类型 Delphi有三种类型的字符: ●AnsiChar这是标准的1字节的ANSI字符,程序员都对它比较熟悉. ●WideChar这是2字节的Unicode字符. ●Char在目前Delphi早 ...

  4. 前端观察:HTML5做得好,收入不比 iOS 差

    谷歌奋进的绿色机器人超过了苹果的市场占有率,这一市场现象,导致了愈来愈多的开发者转投html5的怀抱.而HTML5将成为开发者拥抱同时拥抱Android和IOS的不二法门. 根据著名移动生态系统分析公 ...

  5. [BZOJ2809&1455&1367]解题报告|可并堆

    其实非常好理解..就是可以可以合并起来的两个堆嘛>< 2809: [Apio2012]dispatching Description 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依 ...

  6. 20155117王震宇 2006-2007-2 《Java程序设计》第二周学习总结

    学号 2006-2007-2 <Java程序设计>第X周学习总结 教材学习内容总结 学习一门语言首先要熟悉基础的语法,注意不要和之前学过的语言知识混淆. java严格区分大小写. 教材学习 ...

  7. Array和String测试与java.String.split

    java.string.split() 存在于java.lang包中,返回值是一个数组. 作用是按指定字符或者正则去切割某个字符串,结果以字符串数组形式返回. 例 String [] toSort = ...

  8. 6.MySQL简介

    MySQL简介 ·点击查看MySQL官方网站 ·MySQL是一个关系型数据库管理系统,由瑞典MySQLAB公司开发,后来被Sun公司收购,Sun公司后来又被Oracle公司收购,目前属于facle旗下 ...

  9. 重载jquery on方法实现click事件在移动端的快速响应

    额,这个标题取的还真是挺装的... 其实我想表达的是jquery click事件如何在移动端自动转换成touchstart事件. 因为移动端click事件会比touchstart事件慢几拍 移动设备某 ...

  10. discuz2.5登录后台闪退的解决办法

    今天突然发现discuz2.5论坛后台进不去,开始以为密码错了,但发现登录后也是闪退.我试着清除浏览器cookie,也换了其他浏览器也没有用,还是上网找找吧! discuz2.5进入后台闪退的原因: ...