题目来源:大众点评软件开发实习生技术测试;
题目:如题,统计出整数1-N中1出现的次数。如N=12,则1一共在1,10,11,12这四个数中出现了五次;
解法思想:
以12102为例,暂且从左至右分别称为第1位,第2位,到第bit(bit为数目的位数)位。则1为第1位,2为第2位,3为第3位,0位第4位。
1在第1位出现的次数:10000-12102,共有2103次,即count=(2102+1);
1在第2位出现的次数:01000-11999,共有2*1000次,即count=(1+1)*1000,其中1000为第二位的权值,即第二位为千位,所以乘以1000;
1在第3位出现的次数:00100-11199、12100-12102次,即count=12*100+2+1,100为第三位处于100位,所以乘100;
1在第4位出现的次数:00010-12019,即count=121*10;
1在第5位出现的次数:00001-12101,即count=(1210+1)*1;
假设第i位设为当前位cur,位于第i位左边的假设称为高位most,位于第i位右边的假设称为低位least,当前位所处十进制位的权值称为tmp。由上面的分析可知,
当cur=1时,count=tmp*most+least+1;
当cur>1时,count=(tmp+1)*most;
当cur<1时,count=tmp*most。
算法分析就是这样了,那么下面我们的问题便是,给定一个正整数N,如何用编程语言来求出这个整数的位数、当前位,高位,低位和当前位所在位的权值。
位数bit=(int)log10N+1;
第i位所在位的权值tmp=10^(n-i);
当前位cur=(N/tmp)%10;
高位most=(N/10)/tmp;
低位least=N/tmp.
这是核心问题,解决了这些核心问题,剩下的就比较好解决了。下面贴出我的代码,可直接运行。
// test11.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include"iostream"
using namespace std;
unsigned long caculate(unsigned long n){
unsigned long count=0;
int bit = 0;
bit = log10(n)+1;
int tmp = 0;
int cur=0;
int most=0;
int least=0;
for (int i = 0; i < bit; i++)
{
tmp = (int)pow(10, bit-i-1);
cur=(n/tmp)%10;
most=(n/10)/tmp;
least=n%tmp;
if (cur==1)
{
count=count+most*tmp+least+1;
}
else if (cur>1)
{
count=count+most*tmp+tmp;
}
else
{
count=count+most*tmp;
}
}
return count;
}
int _tmain(int argc, _TCHAR* argv[])
{
unsigned long iCount = 0;
unsigned long n = 0;
cout<<"输入你需要统计的数:";
cin>>n;
iCount=caculate(n);
cout<<"总共有"<<iCount<<endl;
return 0;
}