寻找丑数--我的第一篇文章

    本科四年,研究生已经第二年,虽说一直是计算机专业,编码能力越来越弱,面试了几个实习生职位,由于没有准备就去了,不出意外的全悲剧了。下定决心开始努力加强,把理论知识一点一点付诸于实践。从今天开始,每天写一篇代码题,在此立帖为证。。。
    以前经常下载CSDN的东西,现在来这里记录吧,也算做出点贡献。每篇题目必定亲自验证,算法思想会借鉴网上思路,但有自己思考、敲代码。完全是自己记录学习过程,涉及到他人版权,还请见谅。

   题目1:把只包含质因子2、3和5的数称作丑数(Ugly Number),例如:2,3,4,5,6,8,9,10,12,15,等,习惯上我们把1当做是第一个丑数。写一个高效算法,返回第n个丑数。
 
    首先,想到的应该是暴力求解。从1开始循环,判断每个数是不是丑数,当count累加到n时,停止循环。
		
	
	void findugly(int n)
	{
		int i=2;
		int d;
		int count = 1;
		while(count<n)
		{
			d=i;
			while(d%2==0)
			d=d/2;
			while(d%3==0)
				d=d/3;
			while(d%5==0)
				d=d/5;
			if(d==1)
				count++;
			i++;
		}
		printf("第%d个丑数是:%d\n",n,(i-1));
	}


	void main()
	{
		clock_t start, finish;
		double duration;
		start = clock();
		int d ;
		printf("请输入数字:");
		scanf("%d",&d);
		findugly(d);
		finish = clock();
		duration=finish - start;
		printf("%f seconds \n", duration/1000);
	}


	运行结果,请输入数字:1500
			第1500个丑数是:859963392
			26.222000 seconds

      虽然在四核机器上运行,此时程序执行时间还是很长的,原因是循环次数太多,寻找到第1500个丑数时,i已经非常大。如何减少复杂度呢?我们不按照i从一开始依次循环,每个丑数必定只有2 3 5因子,那么它们必定是这几个数相互乘法而得到的,按照此思路,以一个数组ugly[n]来存储丑数,每次从三个相乘后的结果中选择一个最小的存入数组,那么同样可以得到所求结果,并且复杂度降低了。(以下代码摘自网络)
	
	int min(int a, int b, int c)   
	{   
 	   int temp = (a < b ? a : b);   
 	   return (temp < c ? temp : c);   
	}   
	int findugly(int n) 
	{   
	    int *ugly= new int[n];   
	    ugly[0] = 1;   
	    int index2 = 0;   
	    int index3 = 0;   
	    int index5 = 0;   
	    int index = 1;   
	    while (index < n)   
	    {   
	        int val = min(ugly[index2]*2, ugly[index3]*3, ugly[index5]*5); //竞争产生下一个丑数   
	        if (val == ugly[index2]*2) //将产生这个丑数的index*向后挪一位;  
	            ++index2;   
	        if (val == ugly[index3]*3)   //这里不能用elseif,因为可能有两个最小值,这时都要挪动;
	            ++index3;   
	        if (val == ugly[index5]*5)   
	            ++index5;   
	        ugly[index++] = val;   
	    }   
	
	
	    int result = ugly[n-1];   
	    delete[] ugly;   
	    return result;   
	}   
	 
	void main()
	{
		clock_t start, finish;
		double duration;
		start = clock();
		int d ;	
		printf("请输入数字:");
		scanf("%d",&d);	
		printf("%d\n",findugly(d));
		finish = clock();
		duration=finish - start;
		printf("%f seconds\n ", duration/1000);
	}



    运行结果,请输入数字:1500
		   859963392
		   1.596000 seconds
    可见,采取这种方法后,时间非常快,实际上,按照动态规划思想,要求出第n个丑数,必须要遍历前n-1个丑数,那么这已经是最优的了,或与最优相差常数时间。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值