这是一道广为流传的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. mysql5.7主从(Master/Slave)同步配置

    环境: mysql版本都是5.7(以前的版本配置可能不一样) 主(Master) windows:192.168.0.68 从(Slave) centos7:192.168.0.4 基本环境配置: 要 ...

  2. POJ 3171 DP

    Cleaning Shifts Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3563   Accepted: 1205 D ...

  3. 「Django」rest_framework学习系列-API访问跨域问题

    #以中间件方式解决API数据访问跨域问题1.API下新建文件夹下写PY文件a.引入内置类继承: from django.middleware.common import MiddlewareMixin ...

  4. bzoj 3261: 最大异或和 (可持久化trie树)

    3261: 最大异或和 Time Limit: 10 Sec  Memory Limit: 512 MB Description       给定一个非负整数序列 {a},初始长度为 N.       ...

  5. Redhat安装配置VNC服务器

    1. 检查安装VNC服务器 # rpm -qa|grep vnc 如果返回信息中有tigervnc-server,说明已安装了VNC:如果没有: # yum install tigervnc # yu ...

  6. windows 安装elasticsearch-head插件

    es5以上版本安装head需要安装node和grunt(之前的直接用plugin命令即可安装) (一)从地址:https://nodejs.org/en/download/ 下载相应系统的msi,双击 ...

  7. 编程笔记:JavaScript 中的类型检查

    在Badoo的时候我们写了大量的JS脚本,光是在我们的移动web客户端上面就有大概60000行,可想而知,维护这么多JS可是相当具有挑战性的.在写如上规模js脚本客户端应用的时候我们必须对一件事保持警 ...

  8. 【acmm】一道简单的数学题

    emm卡常 我本来写成了这个样子: #include<bits/stdc++.h> using namespace std; typedef long long LL; ; struct ...

  9. 【CodeForces】960 F. Pathwalks 主席树+动态规划

    [题目]F. Pathwalks [题意]给定n个点m条边的有向图,可能不连通有重边有自环.每条边有编号 i 和边权 wi ,求最长的路径(可以经过重复节点)满足编号和边权都严格递增.n,m,wi&l ...

  10. 【NOIP】普及组2009 细胞分裂

    [算法]数论 [题解]均分的本质是A整除B,A整除B等价于A的质因数是B的子集. 1.将m1分解质因数,即m1=p1^a1*p2^a2*...*pk^ak 所以M=m1^m2=p1^(a1*m2)*p ...