原题
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];
}
};