leetcode-Ugly Number(丑数)

问题描述:

我们把只包含因子2,3,5的数称为丑数。求第n个丑数。通常,把1称为第一个丑数。

问题求解:

方法一:挨个判断每个数是不是丑数,即使不是丑数也会对它求余数和除法操作。算法效率不是很高,leetcode会超时。

class Solution {
public:
    int nthUglyNumber(int n) {
        if(n<=0) return 0;

        int cnt=0;
        int num=0;
        while(cnt<n)
        {
            if(isUgly(num)) ++cnt;
            ++num;
        }
        return num-1;
    }

    bool isUgly(int num) {

        if(num == 0) return false;
        while(num%2 == 0)
            num /= 2;
        while(num%3 == 0)
            num /= 3;
        while(num%5 == 0)
            num /= 5;
        return (num==1)?true:false;
    }
};

方法二:创建数组保存已经找到的丑数,空间换时间。

根据丑数的定义,丑数(1除外)应该是另一个丑数乘以2,3或5的结果,因此我们可以创建一个数组,里边的数字是排好序的丑数,每个丑数都由前面的数字乘以2,3或5得到。

1)创建一个长度为n的数组ugly,从小到大顺序存储n个丑数,数组中的首项为1,即第一个丑数为1
2)设置三个变量idx2、idx3、idx5存储下标,初始值都为0
3)找出数组ugly[idx2]*2、ugly[idx3]*3、ugly[idx5]*5的最小值,最小值即为下一个丑数,同时更新最小值对应的下标,如果多个数字同时为最小值,则它们的下标都要更新
直到找到第n个丑数。

class Solution {
public:
    int nthUglyNumber(int n) {
        if(n<=0) return 0;
        vector<int> ugly(n);//(1)创建存储n个丑数的数组
        ugly[0] = 1;//第一个丑数为1
        //(2)下标为idx2的丑数乘以2后恰好是最开始大于数组中已有的最大丑数
        //同理,下标为idx3,idx5也是这样。记录该位置,每次去更新这个下标即可
        int idx2=0, idx3=0, idx5=0;
        int cnt=1;//记录数组中丑数下标
        while(cnt < n)
        {   //(3)找出3者最小值,即为下一个丑数
            int min=minOf3(ugly[idx2]*2, ugly[idx3]*3, ugly[idx5]*5);
            //(4)看最小值是三者中哪一个,更新其对应下标
            if(min == ugly[idx2]*2)
            {
                ++idx2;
            }
            if(min == ugly[idx3]*3)
            {
                ++idx3;
            }
            if(min == ugly[idx5]*5)
            {
                ++idx5;
            }
            ugly[cnt]=min;//(5)将下一个丑数存到数组
            ++cnt;//(6)找下一个位置的丑数
        }
        return ugly[n-1];
    }

    int minOf3(int a, int b, int c)
    {
        int m=a<b?a:b;
        return m<c?m:c;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值