超級丑數 是一個正整數,并滿足其所有質因數都出現在質數數組 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] 中。
解題思路(最小堆)
使用優先隊列,逐個生成超級丑數,那么生成的第n小的丑數,就是我們需要的
代碼
class Solution {public int nthSuperUglyNumber(int n, int[] primes) {PriorityQueue<Long> priorityQueue=new PriorityQueue<>();priorityQueue.add(1L);Set<Long> set=new HashSet<>();set.add(1L);int i=0;while (!priorityQueue.isEmpty()){long cur = priorityQueue.poll();if (++i==n)return (int) cur;for (int prime : primes) {if (set.contains(cur*prime))continue;set.add(cur*prime);priorityQueue.add(cur*prime);}}return -1;}
}
解題思路(dp)
- 使用動態規劃,dp[i]代表第i個丑數
- 這題類似與丑數二,我們需要對質數數組中的每個質數,維護一個指針,指向第p[i]個丑數,因為在樸素的做法中,需要對丑數乘以所有質數數組中的數字,所以我們維護的指針數組作用就是表示:第p[j]-1個丑數*primes[j]的結果已經加入dp數組了,現在需要加入dp數組的是p[j]個丑數 * primes[j]
代碼
class Solution {public int nthSuperUglyNumber(int n, int[] primes) {int[] dp = new int[n+1];int[] p=new int[primes.length];Arrays.fill(p,1);dp[1]=1;for (int i=2;i<=n;i++){int min=Integer.MAX_VALUE;for (int j = 0; j < primes.length; j++) {min= Math.min(min,primes[j]*dp[p[j]]);}dp[i]=min;for (int j = 0; j < primes.length; j++) {if(primes[j]*dp[p[j]]==min){p[j]++;}}}return dp[n];}
}