您的位置:首页 > 职场人生

面试题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的数目,用递归来求解。

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: