剑指Offer学习总结-从1到n整数中1出现的次数
2018-01-23 21:37
316 查看
剑指Offer学习总结-从1到n整数中1出现的次数
本系列为剑指Offer学习总结,主要是代码案例的分析和实现:书籍链接:http://product.dangdang.com/24242724.html
原作者博客:http://zhedahht.blog.163.com/blog/static/254111742011101624433132/
原作者博客链接有完整的项目代码下载。
从1到n整数中1出现的次数
题目
题目:输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数。例如输入12,从1到12这些整数中包含1的数字有1,10,11和12,1一共出现了5次。第一眼看到的解法:
累加 1 到 n 中每个整数 1 出现的次数。 求每个整数的1的个数,我们可以每次通过对 10 求余数判断整数的个位数字是不是 1。
如果这个数字大于 10, 除以 10 之后再判断个位数字是不是 1。
int NumberOf1Between1AndN_Solution1(unsigned int n) { int number = 0; for(unsigned int i = 1; i <= n; ++ i) number += NumberOf1(i); return number; } int NumberOf1(unsigned int n) { int number = 0; while(n) { if(n % 10 == 1) number ++; n = n / 10; } return number; }
分析规律解法:
找规律的办法,其实也是有简单到复杂,由一般到特殊,通过举例分析的办法来进行。如果希望不用计算每个数字的1的个数,那就只能去寻找1在数字中出现的规律了。为了找到规律,我们不妨用一个稍微大一点的数字如21345作为例子来分析。
把数字分为2段,一段是1~1345,另一段是1346~21345.
(1)1345~21345中,万位上出现1的数字在10000~19999中,有10^4个。如果n的长度为length,则共有10^(length-1)次。
(2)如果首位数字等于1,比如从10000~12345,则最高位出现1的次数为2345+1=2346次,即共有atoi(strN+1)+1次。
(3)除了第一位的数之外,其他位上有1的次数:由于最高位是2,我们再把1346~21345分成2段,1346~11346,11236~21346,每一段剩下的4位数字中,选择其中一位是1,其余三位可以在0~9这10个数字中任选,
因此根据排序组合的原则,总共出现的次数是2*4*10^3=8000次
所以有2*10^3次。即共有first*(length - 1)*10^(length-2)次。
(4)1~1345中1的次数,就是21345中除去首位之后的次数。迭代求得。
int NumberOf1Between1AndN_Solution2(int n) { if(n <= 0) return 0; char strN[50]; sprintf(strN, "%d", n); return NumberOf1(strN); } int NumberOf1(const char* strN) { if(!strN || *strN < '0' || *strN > '9' || *strN == '\0') return 0; int first = *strN - '0'; unsigned int length = static_cast<unsigned int>(strlen(strN)); if(length == 1 && first == 0) return 0; if(length == 1 && first > 0) return 1; // 假设strN是"21345" // numFirstDigit是数字10000-19999的第一个位中1的数目 int numFirstDigit = 0; if(first > 1) numFirstDigit = PowerBase10(length - 1); else if(first == 1) //这里指针+1则指向了下一位 也就是1345 numFirstDigit = atoi(strN + 1) + 1; // numOtherDigits是01346-21345除了第一位之外的数位中1的数目 int numOtherDigits = first * (length - 1) * PowerBase10(length - 2); // numRecursive是1-1345中1的数目 int numRecursive = NumberOf1(strN + 1); return numFirstDigit + numOtherDigits + numRecursive; } int PowerBase10(unsigned int n) { int result = 1; for(unsigned int i = 0; i < n; ++ i) result *= 10; return result; }
相关文章推荐
- 剑指Offer学习总结-数字在排序数组中出现的次数
- 剑指Offer学习总结-数组中出现次数超过一半的数字
- 【剑指Offer学习】【面试题32:求从1到n的整数中1出现的次数】
- 剑指offer 面试题32:从1到n整数中1出现的次数(leecode233. Number of Digit One) 题解
- 剑指Offer_31_整数中1出现的次数(从1到n整数中1出现的次数)
- 【剑指offer】面试题 43 : 1~n 整数中 1 出现的次数
- 剑指Offer面试题32:从1到n整数中1出现的次数 Java实现
- 【九度OJ1373】|【剑指offer32】整数中1出现的次数(从1到n整数中1出现的次数)
- 剑指Offer之从1到n整数中1出现的次数
- 剑指offer 32-从1到n整数中1出现的次数
- 剑指offer--面试题32:整数中1出现的次数(从1到n整数中1出现的次数)
- 剑指offer-5-面试32:从 1 到 n 整数中 1 出现的次数(时间效率)
- 剑指offer-整数中1出现的次数
- 剑指offer——整数中1出现的次数(从1到n整数中1出现的次数)
- 剑指offer----整数中1出现的次数(从1到n整数中1出现的次数)
- 剑指offer-整数中1出现的次数(从1到n整数中1出现的次数)
- 【剑指Offer学习】【面试题29 :数组中出现次数超过一半的数字】
- 剑指Offer_43 1~n整数中1出现的次数
- 剑指offer面试题[32]:从1到n整数中1出现的次数
- 剑指offer 整数中1出现的次数