面试题36:从1到n整数中1出现的次数

来源:互联网 发布:网络机顶盒怎么设置 编辑:程序博客网 时间:2024/05/17 09:01

题目:

输入一个整数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;}


0 0
原创粉丝点击