从1到N整数中1出现的次数
文章目录
//给定数字N,计算从1~N中各个数字位上包含1的个位
#include <iostream>
#include<stdio.h>
#include<string.h>
#include<cstring>
#include<algorithm>
using namespace std;
//方法1,暴力穷举,一个数需要o(logn),一共需要n*O(logn)
int NumberOf1(unsigned int n){
int number=0;
while(n){//从个位往高位计算给定的数字n包含的数字1的个数
if(n%10==1)
number++;
n=n/10;
}
return number;
}
int NumberOf1Between1AndN(unsigned int n){
int number=0;
for(int i=1;i<=n;i++)
number+=NumberOf1(i);
return number;
}
//方法二,递归
//数字转换为 字符串更方便//递归一次去掉一位,所以时间复杂度编程O(logn)
int PowerBase10(unsigned int n){
int result=1;
for(unsigned int i=0;i<n;i++)
result*=10;
return result;
}
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"
//numberFirstDigit是数字10000~19999的第一个位中的数目
int numFirstDigit=0;
if(first>1)
numFirstDigit=PowerBase10(length-1);
else if(first==1)
numFirstDigit=atoi(strN+1)+1;
//numberOtherDigits是1346~21346除第一位之外的数位中的数目
int numOtherDigits=first*(length-1)*PowerBase10(length-2);
//numRecursive是1~1345中的数目
int numRecursive=NumberOf1(strN+1);
return numFirstDigit+numOtherDigits+numRecursive;
}
int NumberOf1Between1AndN(int n){
if(n<=0)
return 0;
char strN[50];
sprintf(strN,"%d",n);
return NumberOf1(strN);
}
int main()
{
cout<<NumberOf1Between1AndN(21345);
//cout<<PowerBase10(2);
return 0;
}