寻找丑数


定义: 把只包含质因子2、3和5的数称作丑数(Ugly Number),例如:2,3,4,5,6,8,9,10,12,15,等,习惯上我们把

1当做是第一个丑数。写一个高效算法,返回第n个丑数。


最普通(也最耗时)的做法是从1开始遍历,然后判断这个数的因式分解中只包含2,3,5,满足则找到了一个,一直找

下去,直到第n个被找出!


分析:

假设数组ugly[N]中存放不断产生的丑数,初始只有一个丑数ugly[0]=1,由此出发:

1:下一个丑数由因2,3,5竞争产生,得到ugly[0]*2, ugly[0]*3, ugly[0]*5, 显然最小的那个数是新的丑数,

所以第2个丑数为ugly[1]=2;

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;

3:重复这个过程,直到第n个丑数产生。总之:每次竞争中有一个(也可能是两个)因子胜出,下一次竞争中 胜出

的因子就应该加大惩罚!


#include <iostream>
#include <cstdio>
#include <string>
#include <string.h>
#include <map>
#include <vector>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <queue>
#include <set>
#include <stack>
#include <functional>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <numeric>
#include <cassert>
#include <bitset>
#include <stack>
#include <ctime>
#include <list>
#define INF 0x7fffffff
#define max3(a,b,c) (max(a,b)>c?max(a,b):c)
#define min3(a,b,c) (min(a,b)<c?min(a,b):c)
#define mem(a,b) memset(a,b,sizeof(a))
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 [50000];
    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];
    return result;
}

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


参看POJ2545:http://blog.youkuaiyun.com/acm_zl/article/details/10616109

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值