剑指Offer——面试题43:从1到n整数中1出现的次数

面试题43:从1到n整数中1出现的次数
题目:输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数。例如输入12,从1到12这些整数中包含1 的数字有1,10,11和12,1一共出现了5次。

解决方法:

  • ◈不考虑时间效率的解法,靠它想拿到 Offer 有点难
#include<iostream>
#include<algorithm>
#include<set>
#include<vector>
using namespace std;
int NumberOf1(unsigned int n){
	int number=0;
	while(n){
		if(n%10==1) number++;
		n/=10;
	}
	return number;
}
int NumberOf1Between1AndN(unsigned int n){
	int number=0;
	for(unsigned int i=1;i<=n;i++){
		number+=NumberOf1(i);
	}
	return number;
}
int main() {
	printf("%d\n",NumberOf1Between1AndN(100)); 
	return 0;
}
  • ◈从数字规律着手明显提高时间效率的解法,能让面试官耳目一新
#include<iostream>
#include<algorithm>
#include<set>
#include<vector>
#include<cstring>
#include<cmath>
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=static_cast<unsigned int>(strlen(strN));
	
	if(length==1 && first==0) return 0;
	if(length==1 && first>1) return 1;
	
	// 假设 strN 是 "21345"
	// numFirstDigit 是数字 10000~19999 的第一位中的数目
	int numFirstDigit=0;
	if(first>1) numFirstDigit=(int)pow(10, length-1);
	else if(first==1) numFirstDigit=atoi(strN+1)+1;
	
	// numOtherDigits 是 1346~21345 除第一位之外的数位中的数目
	int numOtherDigits=first*(length-1)*((int)(pow(10, 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() {
	printf("%d\n",NumberOf1Between1AndN(21345)); 
	return 0;
}
发布了46 篇原创文章 · 获赞 47 · 访问量 1407

猜你喜欢

转载自blog.csdn.net/qq_35340189/article/details/104443814