「这是我参与2022首次更文挑战的第4天,活动详情查看:2022首次更文挑战」。
过了这个周五,应该就算正式进入过年的倒计时了。朋友圈也开始刷一些拜年的照片,过年气氛渐浓。继续一天一题leetcode,坚持练习才会有结果。
题目
超级丑数 是一个正整数,并满足其所有质因数都出现在质数数组 primes 中。
给你一个整数 n 和一个整数数组 primes ,返回第 n 个 超级丑数 。
题目数据保证第 n 个 超级丑数 在 32-bit 带符号整数范围内。
示例 1:
输入: n = 12, primes = [2,7,13,19]
输出: 32
解释: 给定长度为 4 的质数数组 primes = [2,7,13,19],前 12 个超级丑数序列为:[1,2,4,7,8,13,14,16,19,26,28,32] 。
示例 2:
输入: n = 1, primes = [2,3,5]
输出: 1
解释: 1 不含质因数,因此它的所有质因数都在质数数组 primes = [2,3,5] 中。
思路
这个题目其实也是之前做过题目的一个变种,可以查看《leetcode-丑数 II》。
方法是一样的,只不过之前题目规定的质因子是2、3、5,这次是一个可变的数组,原理是一样的。
我们可以把这个超级丑数数组分成len个子数组,字数组0是所有包含因为prime[0]这个因子的超级丑数字数组,字数组1是所有包含因为prime[1]这个因子的超级丑数字数组...字数组len-1是所有包含因为prime[len-1]这个因子的超级丑数字数组。对于每个子数组内部,都存在f[k] = f[k-1]*prime[n]。所以,我们其实只是对这len-1个有序的字数组归并排序,就能得到丑数数组的顺序了。注意:由于一个丑数可能包含多个质因子,所以同一个丑数可能出现在多个字数组中。
定义一个长度为n的数组,uglyNumber,因为数组从0开始,所以uglyNumber[n]代表的是第n+1个超级丑数。然后定义一个长度为len的数组,index,index[m]代表是下标为m的质因子对应子超级丑数数组的下标,那么uglyNumber[n+1] = min(uglyNumber[index[0]]*prime[0], uglyNumber[index[1]]*prime[1]...uglyNumber[index[len-1]]*prime[len-1])。然后求出uglyNumber[n+1]之后,再次遍历index[],如果uglyNumber[n+1] == uglyNumber[index[k]]*prime[k],那么index[k]++。
Java版本代码
class Solution {
public int nthSuperUglyNumber(int n, int[] primes) {
if (n == 1) {
return 1;
}
int len = primes.length;
int[] index = new int[len];
int[] uglyNumber = new int[n];
uglyNumber[0] = 1;
for (int i = 1; i < n; i++) {
int temp = Integer.MAX_VALUE;
for (int j = 0; j < len; j++) {
temp = Integer.min(temp, uglyNumber[index[j]] * primes[j]);
}
uglyNumber[i] = temp;
for (int j = 0; j < len; j++) {
if (temp == uglyNumber[index[j]] * primes[j]) {
index[j]++;
}
}
}
return uglyNumber[n-1];
}
}