寻找丑数
2012-08-06 14:00
316 查看
题目:我们把只包含因子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,则该数是素数,否则是丑数。
代码如下:
上面计算中主要的不足在于,逐一遍历,这样对于不是丑数的数的判断会造成大量的时间浪费,如果能够根据已经计算好的丑数,计算出下一个丑数就可以避免这种情况,实现从丑数到丑数的高效算法,根据定义可知,后面的丑数肯定是前面已知丑数乘以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}即可
代码如下:
分析:寻找一个数是不是满足某种数(质数,水仙数)等,最简单的方法就是遍历,对于任意一个丑数必定可以写成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,则该数是素数,否则是丑数。
代码如下:
1 #include 2 #include<string> 3 using namespace std; 4 5 //判断一个给定的数number是否是丑数 6 bool IsUgly(int number) 7 { 8 while(number % 2 == 0) 9 { 10 number /= 2; 11 } 12 while(number % 3 ==0) 13 { 14 number /= 3; 15 } 16 while(number % 5 ==0) 17 { 18 number /= 5; 19 } 20 return(number == 1)?true:false; 21 } 22 23 //返回从1开始第index个丑数 24 int GetUglyNumber(int index) 25 { 26 if(index <= 0) 27 { 28 return 0; 29 } 30 31 int number=0; 32 int count=0; 33 while(count < index) 34 { 35 ++number; 36 if(IsUgly(number)) 37 { 38 ++count; 39 } 40 41 } 42 43 return number; 44 } 45 46 int main() 47 { 48 cout<<"Enter A Number:"<<ENDL; 49 int idx=0; 50 cin>>idx; 51 cout<<GETUGLYNUMBER(IDX)<<ENDL; 52 return 0; 53 }
上面计算中主要的不足在于,逐一遍历,这样对于不是丑数的数的判断会造成大量的时间浪费,如果能够根据已经计算好的丑数,计算出下一个丑数就可以避免这种情况,实现从丑数到丑数的高效算法,根据定义可知,后面的丑数肯定是前面已知丑数乘以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}即可
代码如下:
1 #include 2 #include<string> 3 using namespace std; 4 5 //返回三个数中的最小者 6 int Min(int number1,int number2,int number3) 7 { 8 int min = (number1 < number2) ? number1 : number2; 9 min = (min < number3) ? min : number3; 10 return min; 11 } 12 13 //返回第index个丑数 14 int GetUglyNumber(int index) 15 { 16 if(index <= 0) 17 { 18 return 0; 19 } 20 21 int *pUglyNumbers = new int[index]; 22 pUglyNumbers[0] = 1; 23 int nextUglyIndex = 1; 24 25 int *pMultiply2 = pUglyNumbers; 26 int *pMultiply3 = pUglyNumbers; 27 int *pMultiply5 = pUglyNumbers; 28 29 while(nextUglyIndex < index) 30 { 31 int min = Min(*pMultiply2 * 2,*pMultiply3 * 3,*pMultiply5 * 5); 32 pUglyNumbers[nextUglyIndex] = min; 33 34 while(*pMultiply2 * 2 <= pUglyNumbers[nextUglyIndex]) 35 { 36 ++pMultiply2; 37 } 38 while(*pMultiply3 * 3 <= pUglyNumbers[nextUglyIndex]) 39 { 40 ++pMultiply3; 41 } 42 while(*pMultiply5 * 5 <= pUglyNumbers[nextUglyIndex]) 43 { 44 ++pMultiply5; 45 } 46 47 ++nextUglyIndex; 48 } 49 50 int ugly = pUglyNumbers[nextUglyIndex-1]; 51 delete[] pUglyNumbers; 52 return ugly; 53 54 } 55 56 int main() 57 { 58 cout<<"Enter A number:"<<ENDL; 59 int number=0; 60 cin>>number; 61 cout<<GETUGLYNUMBER(NUMBER)<<ENDL; 62 return 0; 63 }
相关文章推荐
- [置顶] 经典算法题——寻找第1500个丑数
- google面试题目:寻找丑数
- 2014华为机试,寻找丑数。
- 寻找丑数 【微软面试100题 第六十四题】
- 寻找第K个丑数
- 【剑指Offer-时间效率平衡】寻找第N个丑数
- 寻找丑数
- POJ 1338 Ugly Numbers 寻找丑数
- 寻找丑数
- 寻找丑数问题 HDOJ 1058 Humble Numbers
- 寻找丑数(运算)
- 寻找丑数
- 每天一道算法题19 寻找丑数
- 寻找丑数--我的第一篇文章
- 笔试算法题(20):寻找丑数 & 打印1到N位的所有的数
- 2014华为机试,寻找丑数。
- 寻找丑数 【微软面试100题 第六十四题】
- 程序员面试题精选100题(37)-寻找丑数