每日一算法---寻找丑数
2016-03-20 12:42
344 查看
题目:我们把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第1500个丑数。
分析:寻找一个数是不是满足某种数(质数,水仙数)等,最简单的方法就是遍历,对于任意一个丑数必定可以写成2^m*3^n*5^p,因而对于一个丑数,只含有2,3,5因子,也就意味着该数number%2==0;number%3==0;number%5==0,如果一个数能被2整除,我们就连续除以2;能被3整除,我们就连续除以3;能被5整除,我们就连续除以5;如果最后得到1,则该数是素数,否则是丑数。
然而上面的算法特点是逐一遍历,当计算量足够大时该算法的效率愈显低下,这就迫使我们寻找更高效的算法。。。。。。
最终下一个丑数取:min{M2,M3,M5}即可
代码如下:
第二种方法由于不需要在非丑数的整数花费时间,因而时间复杂度要小很多,在C-Free+win7的平台上,index=1500时,方法1的运行时间为40s,方法2的时间是1s;然而方法2需要动态分配内存,占用空间,而方法1则没有这样的内存开销。说白了,第二种方法是用空间换时间。
分析:寻找一个数是不是满足某种数(质数,水仙数)等,最简单的方法就是遍历,对于任意一个丑数必定可以写成2^m*3^n*5^p,因而对于一个丑数,只含有2,3,5因子,也就意味着该数number%2==0;number%3==0;number%5==0,如果一个数能被2整除,我们就连续除以2;能被3整除,我们就连续除以3;能被5整除,我们就连续除以5;如果最后得到1,则该数是素数,否则是丑数。
#include<stdio.h> //判断一个给定的数number是否是丑数 int IsUgly(int number) { while(number % 2 == 0) { number /= 2; } while(number % 3 ==0) { number /= 3; } while(number % 5 ==0) { number /= 5; } return(number == 1)?1:0; } //返回从1开始第index个丑数 int GetUglyNumber(int index) { if(index <= 0) { return 0; } int number=0; int count=0; while(count < index) { ++number; if(IsUgly(number)) { ++count; } } return number; } int main() { int idx = 0; printf("Enter A Number:"); scanf("%d",&idx); printf("%d",GetUglyNumber(idx)); printf("\n"); return 0; }
然而上面的算法特点是逐一遍历,当计算量足够大时该算法的效率愈显低下,这就迫使我们寻找更高效的算法。。。。。。
思考:如果能够根据已经计算好的丑数,计算出下一个丑数就可以避免这种情况,实现从丑数到丑数的高效算法,根据定义可知,后面的丑数肯定是前面已知丑数乘以2,3,5得到的。
我们假设一个数组中已经有若干丑数,并且这些丑数是按顺序排列的,我们把现有的最大丑数记为max,则下一个丑数肯定是前面丑数乘以2,3,5得到的。不妨考虑乘以2得到的情况,我们把数组中的每一个数都乘以2,由于原数组是有序的,因为乘以2后也是有序递增的,这样必然存在一个数M2,它前面的每一个数都是小于等于max,而包括M2在内的后面的数都是大于max的,因为我们还是要保持递增顺序,所以我们取第一个大于max的数M2。同理对于乘以3的情况,可以取第一个大于max的数M3,对于乘以5的情况,可以取第一个大于max的数M5。最终下一个丑数取:min{M2,M3,M5}即可
代码如下:
#include<stdio.h> int getuglynum(int index); int main() { int index; int count = 0; printf("请输入你要找的第几个丑数(其中1为第一个丑数):\n"); scanf("%d",&index); count = getuglynum(index); printf("%d",count); return 0; } int Min(int num1,int num2,int num3) { //printf("%d %d %d\n",num1,num2,num3); int min = (num1 < num2)? num1 : num2; min = (min < num3) ? min : num3; return min; } int getuglynum(int index) { int *data = new int[index]; data[0] = 1; int *data2 = data; int *data3 = data; int *data5 = data; int count = 1; int min = 0; while(count < index){ min = Min(*data2 *2,*data3 *3,*data5 *5); data[count] = min; while(*data2 * 2 <= data[count]){ ++data2; } while(*data3 * 3 <= data[count]){ ++data3; } while(*data5 * 5 <= data[count]){ ++data5; } ++count; } return data[count-1]; }
第二种方法由于不需要在非丑数的整数花费时间,因而时间复杂度要小很多,在C-Free+win7的平台上,index=1500时,方法1的运行时间为40s,方法2的时间是1s;然而方法2需要动态分配内存,占用空间,而方法1则没有这样的内存开销。说白了,第二种方法是用空间换时间。
相关文章推荐
- React Native iOS环境搭建
- IOS Animation-贝塞尔曲线与Layer简单篇(一)
- hdu3608最长回文子串
- COGS 1584. [CTSC2007]挂缀
- Canvas小例子-时钟
- 多线程“基础篇”07之 线程休眠
- 第4周项目3(2)小学生算数能力测试系统
- mac上使用自带svn
- 线程控制 - AfxBeginThread工作者线程的封装类
- 软件包管理之源码编译安装
- git学习笔记
- Linux命令之 find
- cocapods管理三方库
- 第四周项目3.1-随机函数应用于游戏之猜数字游戏
- ffmpeg调用 avformat_open_input失败,返回 -2
- 计算机网络中一些名词解释(一)
- 20145311第三周学习总结
- 夯实基础——继承、super和final关键字
- 类型转换
- socket: (10106) error can not bind socket