面试题36:从1到n整数中1出现的次数
2015-12-30 22:14
495 查看
题目:
输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数。例如输入12,从1到12这些整数中包含1的数字有1,10,11和12,共出现了5次。
边界条件及异常:
n小于1
思路:
看了剑指offer上的思路,终于明白了。
考虑n为21345,假设我们要求f(n)。
1)其中f1为1出现在最高位的情况(即只考虑最高位1的个数),从10000到19999最高位共10000个1。
所以有:
如果最高位大于1:f1=10^(length-1)
如果最高位等于1:f1=n%(10^(length-1))+1
2)f2为去掉最高位后(1345)加1(1346)到21345中不考虑最高位1后其他位的1的个数。
说明:此处用1345+1=1346的目的是为了:1346-21345刚好是20000个数(即凑整)。
为了便于分析f2的数目,我们可以将1346-21345等效为1-20000(计算1的个数时不包括最高位的1)。
由于不考虑最高位,那么f2为1-10000的两倍。不包括最高位,其实就是1-9999中所有数1的个数。
如果个位是1,有10^3种,十,白千位是1,各有10^3种。
重复情况1111重复的四次,刚好1出现了四次,所以重复情况实际上是一个数中1出现的次数。
所以有:
f2=first*(length-1)*10^(length-2)
3)f3为1-1345中1的数目,用递归来求解。
输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数。例如输入12,从1到12这些整数中包含1的数字有1,10,11和12,共出现了5次。
边界条件及异常:
n小于1
思路:
看了剑指offer上的思路,终于明白了。
考虑n为21345,假设我们要求f(n)。
1)其中f1为1出现在最高位的情况(即只考虑最高位1的个数),从10000到19999最高位共10000个1。
所以有:
如果最高位大于1:f1=10^(length-1)
如果最高位等于1:f1=n%(10^(length-1))+1
2)f2为去掉最高位后(1345)加1(1346)到21345中不考虑最高位1后其他位的1的个数。
说明:此处用1345+1=1346的目的是为了:1346-21345刚好是20000个数(即凑整)。
为了便于分析f2的数目,我们可以将1346-21345等效为1-20000(计算1的个数时不包括最高位的1)。
由于不考虑最高位,那么f2为1-10000的两倍。不包括最高位,其实就是1-9999中所有数1的个数。
如果个位是1,有10^3种,十,白千位是1,各有10^3种。
重复情况1111重复的四次,刚好1出现了四次,所以重复情况实际上是一个数中1出现的次数。
所以有:
f2=first*(length-1)*10^(length-2)
3)f3为1-1345中1的数目,用递归来求解。
#include <iostream> #include <vector> #include <queue> #include <string> #include <stack> #include <algorithm> #include <hash_set> //for hashtable #include <hash_map> #include <set> #include <ctime> using namespace std; int NumberOf1(const char* strN) { if (!strN || *strN<'0' || *strN>'9' || *strN == '\0') return 0; int first = *strN - '0'; unsigned int length = strlen(strN); if (length == 1 && first == 0) return 0; if (length == 1 && first > 0) return 1; int numFirstDigit = 0; if (first > 1) numFirstDigit = (int)pow(10, length - 1); else if (first == 1) numFirstDigit = atoi(strN + 1) + 1; int numOtherDigits = first*(length - 1)*(int)pow(10, length - 2); return numFirstDigit + numOtherDigits + NumberOf1(strN + 1); } int getNumOf1(int n) { if (n <= 0) return 0; char strN[50]; sprintf_s(strN, 50, "%d", n); //n转为字符串 return NumberOf1(strN); } int main() { cout << getNumOf1(123) << endl; return 0; }
相关文章推荐
- java程序员工作三年的修行之路
- 面试干货
- 程序员如何谋划出月薪3万
- 程序员到底需要学习多少东西??
- C#与.NET程序员面试宝典 Day2
- 第一份程序员的自述
- 面试题35:连续子数组的最大和
- 下半年过了中项,感谢学院,感谢薛老师,后面就跟着学院的各位老师学与考了
- 下半年过了中项,感谢学院,感谢薛老师,后面就跟着学院的各位老师学与考了
- 下半年过了中项,感谢学院,感谢薛老师,后面就跟着学院的各位老师学与考了
- 那些年我准备的前端面试题集合
- SQL Server DBA面试知识点(五)-- 索引与执行计划
- JAVA多线程和并发基础面试问答
- 15个顶级Java多线程面试题及回答
- 面试干货——年底干货大放送,你准备好了吗?
- 杨辉三角与一道经典笔试面试题目
- iOS面试题11- NSThread/NSOperation/GCD的优缺点总结
- 程序员技术练级攻略
- 假如编程易懂得,那么程序员就不会热情地写出注释,也不会有得到编程的快乐。
- 求职面试总结