二十四、Json斷言
難度 medium
超級醜數 是一個正整數,並滿足其所有質因數都出現在質數陣列 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] 中。
提示:
1 <= n <= 106
1 <= primes.length <= 100
2 <= primes[i] <= 1000
題目資料 保證 primes[i] 是一個質數
primes 中的所有值都 互不相同 ,且按 遞增順序 排列
解題思路1:這道題目和264. 醜數 II是很相似的,可以用同樣的方法解決。由於題目給定的質因數不再是2,3,5,而是一個數組,我們也可以用一個數組idx來記錄每個質因數的最新idx[i],idx[i]表示第i個質因數在結果陣列dp中的下標,該下標對應的醜數就是第i個質因數為了構建一個新的醜數使用的上一個醜數。當構建出當前醜數的時候,我們利用質因數陣列找到構建出當前醜數的上一個醜數的下標,然後更新其下標。其實思路和
程式碼 t77 s80 java
class Solution { public int nthSuperUglyNumber(int n, int[] primes) { int len = primes.length; int[] dp = new int[n]; dp[0] = 1; int[] idx = new int[len]; for(int i=1; i<n; i++){ dp[i] = Integer.MAX_VALUE; for(int j=0; j<len; j++){ // 找到當前最小的醜數 dp[i] = Math.min(dp[i], dp[idx[j]] * primes[j]); } for(int j=0; j<len; j++){ // 找到構建出當前醜數的上個醜數的下標,並加一 // 表示那個醜數對應的情況已經涵蓋了,需要往後考慮下一個醜數了 if(dp[i]==dp[idx[j]]*primes[j]){ idx[j]++; } } } return dp[n-1]; } }
解題思路2:其實這道題目還可以用最小堆的方法解決,堆頂始終是目前構建的所有醜數中的最小值,每次取出當前的最小丑數,並且和質因數陣列(也就是初始醜數陣列)進行相乘,將得到的新的醜數入堆,直到出堆的醜數個數達到要求。這種方法其實就是無腦暴力方法,只要沒達到個數要求,就一直構建醜數,然後利用最小堆的排序功能,每次都取出當前最小丑數,這樣相當於就是按順序排好了所有醜數,直到達到個數要求就返回,多的醜數就不管了。
程式碼 java t28 s5
class Solution {
public int nthSuperUglyNumber(int n, int[] primes) {
HashSet<Long> set = new HashSet<>();
PriorityQueue<Long> q = new PriorityQueue<>();
set.add(1L);
q.add(1L);
while(n-->0){
long t = q.poll();
if(n==0) return (int)t;
for(int p : primes){
if(!set.contains(t*p)){
set.add(t*p);
q.add(t*p);
}
}
}
return -1;
}
}
參考資料:
https://www.cnblogs.com/grandyang/p/5144918.html
https://leetcode-cn.com/problems/super-ugly-number/solution/gong-shui-san-xie-yi-ti-shuang-jie-you-x-jyow/