264. 醜數 II (JAVA)
阿新 • • 發佈:2022-05-15
給你一個整數 n ,請你找出並返回第 n 個 醜數 。
醜數 就是隻包含質因數 2、3 和/或 5 的正整數。
示例 1:
輸入:n = 10
輸出:12
解釋:[1, 2, 3, 4, 5, 6, 8, 9, 10, 12] 是由前 10 個醜陣列成的序列。
示例 2:
輸入:n = 1
輸出:1
解釋:1 通常被視為醜數。
提示:
1 <= n <= 1690
思路I:醜數都是由之前的數,與2,3,5相乘獲得的 => 動態規劃
class Solution { public int nthUglyNumber(int n) { int p2 = 1, p3 = 1, p5 = 1; //指向下一個給2、3、5相乘的醜數的位置 int[] dp = new int[n+1]; dp[1] = 1; for(int i = 2; i <= n; i++){ dp[i] = Math.min(dp[p2]*2, Math.min(dp[p3]*3, dp[p5]*5)); if(dp[i] == dp[p2]*2) { p2++; } if(dp[i] == dp[p3]*3) { //要用3個if,因為可能存在多個最小值,比如2*3,3*2都等於6p3++; } if(dp[i] == dp[p5]*5) { p5++; } } return dp[n]; } }
思路II:使用最小堆,每次將堆中的最小值出堆,出堆後將其*2, *3, *5的數入堆。Java中可以使用優先佇列實現最小堆。
class Solution { public int nthUglyNumber(int n) { Queue<Integer> priorityQueue = newPriorityQueue<>(); priorityQueue.add(1); int count = 0; int curNumber = 1; long nextNumber; while(!priorityQueue.isEmpty()){ count++; curNumber = priorityQueue.peek(); while(!priorityQueue.isEmpty() && priorityQueue.peek() == curNumber) { priorityQueue.remove(); } if(count >= n){ break; } nextNumber = (long)curNumber * 2; if(nextNumber == curNumber*2) { //防止溢位 priorityQueue.add(curNumber*2); } nextNumber = (long)curNumber * 3; if(nextNumber == curNumber*3) { priorityQueue.add(curNumber*3); } nextNumber = (long)curNumber * 5; if(nextNumber == curNumber*5) { priorityQueue.add(curNumber*5); } } return curNumber; } }