网址:
https://leetcode.com/problems/super-ugly-number/
Hint:
https://leetcode.com/problems/ugly-number-ii/ 为此题的特殊情况,aka简化版,可先看或忽略
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.
Example:
Input: n = 12, primes = [2,7,13,19]
Output: 32
Explanation: [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.
Solution1
思路:
maintain一个minHeap,一共pop n次,每pop一次,将pop出的数与prime中每一个相乘,存入heap中
Error1:
忘记去重,pop 2时,offer 2 * 7,pop 7时,重复offer 14,故添加Set deduplicate
复杂度:
k = prime.length
Time: O(n * k * log(nk))
Space: O(n * k)
public int nthSuperUglyNumber(int n, int[] primes) {
PriorityQueue<Integer> qp = new PriorityQueue<>();
Set<Integer> dedup = new HashSet<>();
qp.offer(1);
dedup.add(1);
while(n > 1) {
n--;
int cur = qp.poll();
for (int prime : primes) {
int multi = prime * cur;
if (!dedup.contains(multi)) {
//offer Time compelexity: log(size)
qp.offer(multi);
dedup.add(multi);
}
}
}
return qp.poll();
}
问题:超时
原因:当n * k很大时,每次offer都需要log(nk),超时。其实后面的super 大的数字都用不到,我们只需要前n个数
Solution2
思路:
已知,每次的当前最小值,只可能是已生成的ugly number与prime数组中的数相乘而得到
添加一个idx数组,保存for prime中的每一个数,已经与那些已生成ugly数组中的数相乘完毕,i.e.,下一个可能最小值是由prime与ugly[index]产生
Hint:同理,第二个j的for循环,deduplicate
复杂度:
k = prime.length
Time: O(n * k)
Space: O(n * k)
public int nthSuperUglyNumber(int n, int[] primes) {
int[] ugly = new int[n];
int[] idx = new int[primes.length];
ugly[0] = 1;
for (int i = 1; i < n; i++) {
//find next
ugly[i] = Integer.MAX_VALUE;
for (int j = 0; j < primes.length; j++) {
ugly[i] = Math.min(ugly[i], primes[j] * ugly[idx[j]]);
}
//slip duplicate
for (int j = 0; j < primes.length; j++) {
if (primes[j] * ugly[idx[j]] == ugly[i]) {
idx[j]++;
}
}
}
return ugly[n - 1];
}
to do
https://leetcode.com/problems/super-ugly-number/discuss/?orderBy=most_votes
还有两个优化 or trade off,等我缓缓明天复习再看