寻找丑数

诺西笔试最后一道题,题意:
把只包含质因子2、3和5的数称作丑数(Ugly Number),例如:2,3,4,5,6,8,9,10,12,15,等,习惯上我们把1当做是第一个丑数。
写一个高效算法,返回第n个丑数。

最普通(也最耗时)的做法是从1开始遍历,然后判断这个数的因式分解中只包含2,3,5,满足则找到了一个,一直找下去,直到第n个被找出!测试了一下,找第1500个丑数耗时40秒!

分析:假设数组ugly[N]中存放不断产生的丑数,初始只有一个丑数ugly[0]=1,由此出发,下一个丑数由因子2,3,5竞争产生,得到ugly[0]*2, ugly[0]*3, ugly[0]*5, 显然最小的那个数是新的丑数,所以第2个丑数为ugly[1]=2,开始新一轮的竞争,由于上一轮竞争中,因子2获胜,这时因子2应该乘以ugly[1]才显得公平,得到ugly[1]*2,ugly[0]*3,ugly[0]*5, 因子3获胜,ugly[2]=3,同理,下次竞争时因子3应该乘以ugly[1],即:ugly[1]*2, ugly[1]*3, ugly[0]*5, 因子5获胜,得到ugly[3]=5,重复这个过程,直到第n个丑数产生。总之:每次竞争中有一个(也可能是两个)因子胜出,下一次竞争中 胜出的因子就应该加大惩罚!

程序如下所示(只要把程序中的因子改一下就可以得到新的题目),耗时忽略不计:
运行结果:第1500个丑数:859963392, 第1691个丑数2 125 764 000,第1692个丑数就越界了。
int表示的最大整数是2,147,483,647,可由std::cout<<(std::numeric_limits<int>::max)()<<"\n";给出!

#include <iostream>   
using namespace std;   
  
int mymin(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 = mymin(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;   
    }
   
 
/*/
    for (int i = 0; i < n; ++i)   
        cout << ugly[i] << endl;   
 //
*/

    
int result = ugly[n-1];   
    delete[] ugly;   
    
return result;   
}
   
 
int main()   
{   
    
int num=1;
      printf("input the number: \n");
    scanf(
"%d"&num);
    printf(
"%d \n",FindUgly(num));   
    
return 0;   
}


posted on 2010-10-24 21:25 oliver 阅读(3825) 评论(0)  编辑 收藏 引用 所属分类: Algorithm


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

导航

统计

常用链接

留言簿

随笔档案

文章分类

文章档案

个人专栏

技术网站

搜索

最新评论

阅读排行榜

评论排行榜