问题
找到第n个超级丑数。超级丑数是正数,且它的所有质因数都在给定的质数列表中。
246是313的特殊情况,即指定质因子的个数和值。第一个丑数是1。
输入: n = 12, primes = [2,7,13,19]
输出: 32
解释: [1,2,4,7,8,13,14,16,19,26,28,32] 是给定大小为4的质数数组 [2,7,13,19]的前12个丑数序列.
解析
一种最直观的解法是,暴力枚举:不管三七二十一,首先丑数列表是[1],然后每个质数都乘上丑数列表里面的数,得到[1,2,3,5];然后再乘一次得到[1,2,3,5,4,6,10,6,9,15,10,15,25],这样会得到重复的而且没有顺序的结果,所有需要去重后排序,这样复杂度太高…
我们换个思路考虑,假设三个质数是2,3,5,那么第二个丑数一定是
n
u
m
[
1
]
=
M
i
n
(
1
∗
2
,
1
∗
3
,
1
∗
5
)
num[1]=Min(1*2,1*3,1*5)
num[1]=Min(1∗2,1∗3,1∗5),第三个丑数是
n
u
m
[
2
]
=
M
i
n
(
2
∗
2
,
1
∗
3
,
1
∗
5
)
num[2] = Min(2*2,1*3,1*5)
num[2]=Min(2∗2,1∗3,1∗5),第四个丑数是
M
i
n
(
2
∗
2
,
2
∗
3
,
1
∗
5
)
Min(2*2,2*3,1*5)
Min(2∗2,2∗3,1∗5)…
因此,我们只需要记录2,3,5分别乘到第几个丑数位置了。
313超级丑数是进阶版,更一般的情况,这时候创建一个数组来保存每个质数乘到第几个丑数的位置。
Java代码
public int nthSuperUglyNumber(int n, int[] primes) {
int count[] = new int[primes.length];
int num[] = new int[n];
num[0]=1;
int i=1;
for(;i<n;i++){
int temp = Integer.MAX_VALUE;
for(int j=0;j<primes.length;j++){
temp = Math.min(temp,num[count[j]]*primes[j]);
}
num[i] = temp;
for(int j=0;j<primes.length;j++){
if(temp==num[count[j]]*primes[j]){
count[j]++;
}
}
}
return num[n-1];
}
对于246,只需要将primes换成2,3,5可得最终代码。