313. Super Ugly Number

本文介绍了一种求解第n个超级丑数的高效算法。超级丑数是指其所有质因数都在给定质数列表中的正整数。文章详细解释了算法思路,并提供了完整的C++代码实现。

原题

Write a program to find the nth super ugly number.

Super ugly numbers are positive numbers whose all prime factors are in
the given prime list primes of size k. For example, [1, 2, 4, 7, 8,
13, 14, 16, 19, 26, 28, 32] is the sequence of the first 12 super ugly
numbers given primes = [2, 7, 13, 19] of size 4.

Note: (1) 1 is a super ugly number for any given primes. (2) The given
numbers in primes are in ascending order. (3) 0 < k ≤ 100, 0 < n ≤
106, 0 < primes[i] < 1000.

题意大概为找到第n个超级丑数,超级丑数的定义为在给定的一个primes质数数组中,构造超级丑数数组,其中所有数的因子都存在于primes列表中。
其中有一些特别要求:
1. 1是任何给定primes数组的超级丑数。
2. 超级丑数是升序排列的。
3. 0 < k ≤ 100, 0 < n ≤ 106, 0 < primes[i] < 1000.

手动构造超级丑数的列表的时候,可以发现一个规律,每一个新的超级丑数,都是在primes列表里,按照某种乘法方式得到的比现有超级丑数大的最小数(因为升序排序)。因此难点在于如何确定这个“某种乘法”。

先解决了Ugly Number II题后,发现了有这么一个“某种乘法”:
每个新的丑数,都是primes乘上某一个已有的丑数。而且,某个primes乘上了一个已有的丑数以后,再也不会乘到比该丑数小的(也就是排在前面)的丑数,因为会乘出比它小的丑数,不可能再排到那之后。

因此,用一个数组t来记录每一个primes系数乘到了第几个丑数(都是从1开始),每次寻找下一个丑数的时候,遍历该数组,找到乘出来最小的那个新丑数,存到超级丑数数组里。同时,如果这个新的超级丑数是某个prime和它t数组里对应的丑数的乘法结果,那么把该prime在t数组里的下标加一。

代码

class Solution {
public:
    int nthSuperUglyNumber(int n, vector<int>& primes) {
        if(n==1) return 1;
        vector<int> t(primes.size(),0);
        vector<int> v(n);
        v[0] = 1;

        int minn;
        for (int i=1; i<n; i++) {
            minn = INT_MAX;
            for(int j=0; j<t.size(); j++) {
                minn = min(minn, primes[j] * v[t[j]]);
            }

            v[i] = minn;

            for(int j=0; j<t.size(); j++) {
                if(minn == primes[j] * v[t[j]])
                    t[j] ++;
            }
        }


        return v[n-1];
    }
};

相关题目的题解

263. Ugly Number

class Solution {
public:
    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;
    }
};

264. Ugly Number II

class Solution {
public:
    int nthUglyNumber(int n) {
        if(n==1) return 1;
        int t2=0,t3=0,t5=0;
        vector<int> v(n);
        v[0] = 1;
        for(int i=1; i<n; i++) {
            v[i] = min(v[t2] * 2, min(v[t3]*3, v[t5]*5));
            if(v[i] == v[t2] * 2) t2++;
            if(v[i] == v[t3] * 3) t3++;
            if(v[i] == v[t5] * 5) t5++;
        }

        return v[n-1];
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值