[剑指Offer]:丑数


题目描述

我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。

示例:

输入: n = 10
输出: 12
解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 个丑数。
说明:  

1 是丑数。
n 不超过1690。

题解思路

方法一:原始思路

逐个判断每个数是不是丑数,直到丑数的数量达到 n。该方法会超时!!!

class Solution {
public:
    bool determine(int num){
        if(num > 0 && num <= 6) return true;
        else if(num < 0) return false;
        
        while(num % 5 == 0) num /= 5;
        while(num % 3 == 0) num /= 3;
        while(num % 2 == 0) num /= 2;
        return num == 1;
    }
    int nthUglyNumber(int n) {
        int count = 0;
        int i = 0;
        while(count != n){
            if(determine(++i)) ++count;
        }
        return i;
    }
};
方法二:动态规划

上面的方法之所以会超时,是因为我们把每个数都判断了一遍,不管这个数是不是丑数。但是本方法我们只计算丑数,从而大大提升了时间效率。缺点是需要开辟一个长度为 n 的数组来进行动态规划过程。具体思路如下:

  1. 首先我们要发现,任何一个丑数,都是可以由其前面的某个丑数乘2,或乘3,或乘5得到。
  2. 我们先建立一个长度为 n 的 dp 数组,dp[i] 表示第 i + 1 个丑数。
  3. 然后我们设立三个变量:p2, p3, p5,它们都代表 dp 数组中的索引。我们通过选取 dp[p2] * 2, dp[p3] * 3 和 dp[p5] * 5 中的最小值来确定下一个丑数的值。
  4. 当找到了下一个丑数后,假如这个丑数是由 p2 得来的,我们就 ++p2;假如是由 p3 得来的,我们就 ++p3;是由 p5 得来的,我们就 ++p5。这样就可以保证每个丑数都会被找出来。

代码实现:

class Solution {
public:
    int nthUglyNumber(int n) {
        int p2 = 0, p3 = 0, p5 = 0;
        vector<int> dp(n);
        dp[0] = 1;
        for(int i = 1; i < n; ++i){
            dp[i] = min(min(dp[p2]*2, dp[p3]*3), dp[p5]*5);
            if(dp[i] == dp[p2]*2) ++p2;
            if(dp[i] == dp[p3]*3) ++p3;
            if(dp[i] == dp[p5]*5) ++p5;
        }
        return dp[n-1];
    }
};

如有帮助到您,可以多多点赞、评论鼓励哟~~~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值