1214迅速地找出丑数

     今天做九度1214题:把只包含因子235的数称作丑数(UglyNumber)。例如68都是丑数,但14不是,因为它包含因子7

习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。

     1、当然最直观的想法就是一个个数的处理,丑数只能被2,3,5整除。这样如果一个数能被2整除,那就连续除以2。如果能被3整除就连续除以3,如果能被5整除就连续除以5。如果最后的结果为1,说明这个数为丑数,否则不是。

bool IsUgly(int number)

{

    while(number % 2== 0)

        number/= 2;

    while(number % 3== 0)

        number/= 3;

    while(number % 5== 0)

        number/= 5;

    return (number== 1) ? true : false;

}

如果想从小到大找出第N个丑数,那就将正整数一个个处理,直到找到第N个。这种方法思路比较简单。但时间复杂度较高,题目要求1s完成计算,肯定达不到,因此从其他思路进行考虑。


2分析:假设数组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个丑数:8599633921691个丑数2125 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;
}

int result = ugly[n-1];
delete[] ugly;
return result;
}

int main()
{
int num=1;

while(scanf("%d", &num)!=EOF)
      printf("%d \n",FindUgly(num));
return 0;
}

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值