从1到n的数中1出现的个数&&寻找丑数

从1到n的数中1出现的个数,最简单的思路就是从1到n求每个数字中1的个数,这样就是速度太慢了。

可以寻找规律,假设数为abcde,c在百位上,求百位上的数字的方法:如果c等于0或者大于1,1的个数只与左边有关(即ab),如果c等于1,1的个数和左边右边都有关(即de)。

具体见代码:

#include<iostream>
#include<math.h>
#include<time.h>
using namespace std;

int basecalsum(int number){
	int sum =0;
	for(int i =1;i<=number;i++){
		int temp = i;
		while(temp != 0){
			if(temp%10 == 1)
				++sum;
			temp/= 10;
		}
	}
	return sum;
}

int fastcalsum(int number){
	int leftnum,rightnum,curnum,sum =0;
	int pos =1;
	while(number/pos!= 0){
		leftnum = number/(pos*10);
		rightnum= number-(number/pos)*pos;
		curnum = (number/pos)%10;
		switch(curnum){
		case 0:
			sum += leftnum*pos;
			break;
		case 1:
			sum += leftnum*pos+rightnum+1;
			break;
		default:
			sum += (leftnum+1)*pos;
			break;
		}
		pos *=10;
	}
	return sum;
}

int main(){
	clock_t start,end;
	double duration;
	int sum1,sum2;
	start = clock();
	sum1 = basecalsum(100000000);
	end   = clock();
	printf("基本方法输出为%d,损耗时间为%f秒\n",sum1,(double)(end-start)/CLOCKS_PER_SEC);
	start = clock();
	sum1 = fastcalsum(100000000);
	end   = clock();
	printf("快速的方法输出为%d,损耗时间为%f秒\n",sum1,(double)(end-start)/CLOCKS_PER_SEC);
	system("PAUSE");
	return 0;
}

丑数指的是因子中只有2,3,5的数,比如求第1500个丑数也可以一个一个的算,直到1500.如果数字很大还是太慢。

所以我们考虑用空间换时间,即1为最小的丑数,那么其它丑数都可以分解成更小的丑数乘积。所以用数组存储之前的丑数,然后进行计算。为了简化计算可以不用数组中的每个数都来判断,可以每算出一个进行对比,如果是小于则跳过。说的不太清楚,具体看代码。

#include<iostream>
#include<math.h>
#include<time.h>
using namespace std;
//基本方法
bool isurgly(int a){
	while(a%2 == 0)
		a/=2;
	while(a%3 == 0)
		a/=3;
	while(a%5 == 0)
		a/=5;
	return (a==1) ? true : false;
}
int basefindurgly(int number){
	int count = 0;
	int num = 0;
	while(count<number){
		++num;
		if(isurgly(num))
			++count;
	}
	return num;
}
//快速方法
int fastfindurgly(int number){
	//int *urgnum = (int *)malloc(sizeof(number+1));
	int *urgnum = new int[number];
	int pos2,pos3,pos5;
	pos2 = pos3 = pos5 =0;
	urgnum[0] = 1;
	int i =1;
	while(i < number){
		int temp = urgnum[pos2]*2;
		if(temp >urgnum[pos3]*3)
			temp = urgnum[pos3]*3;
		if(temp >urgnum[pos5]*5)
			temp = urgnum[pos5]*5;
		urgnum[i] = temp;
		if(urgnum[pos2]*2 <= urgnum[i])
			++pos2;
		if(urgnum[pos3]*3 <= urgnum[i])
			++pos3;
		if(urgnum[pos5]*5 <= urgnum[i])
			++pos5;
		++i;
	}
	int result = urgnum[number-1];
	delete [] urgnum;
	return result;
}

int main(){
	int result;
	clock_t start,end;
	start = clock();
	result = basefindurgly(1500);
	end = clock();
	printf("结果为%d,时间为%f seconds\n",result,(double)(end-start)/CLOCKS_PER_SEC);
	start = clock();
	result = fastfindurgly(1500);
	end = clock();
	printf("结果为%d,时间为%f seconds\n",result,(double)(end-start)/CLOCKS_PER_SEC);
	system("PAUSE");
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值