編寫一個程序,找出第 n 個醜數。
醜數就是隻包含質因數 2, 3, 5 的正整數。
示例:
輸入: n = 10
輸出: 12
解釋: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 個醜數。
說明:
1 是醜數。
n 不超過1690。
思考:
題解當中幾乎只有兩種思路,最小堆和dp算法(三指針)
dp解法中當前狀態不取決於前一項,而是取決於前面的項數乘以235的最小值,也即是由前面的醜數乘以235的最小值得到新的醜數,而這前面的醜數是由235三個指針確定的,初始是由1乘以235的最小值作爲第二項,隨即2因子做出了貢獻,下一個比較的對象是
2*2,1*3,1*5(3)
2*2,2*3,1*5(2)
3*2,2*3,1*5(5)
3*2,2*3,2*5(2,3)
4*2,3*3,2*5(2)
........
Java代碼:
class Solution {
public int nthUglyNumber(int n) {
if ( n <= 0 ) {
return -1;
}
//最小堆解法
// int h[] = new int[]{2,3,5};
// PriorityQueue<Long> pq = new PriorityQueue<>();
// long res[] = new long[n];
// res[0] = 1;
// for( int i = 0 ; i < n ; i++ ) {
// for( int j = 0 ; j < h.length ; j++ ) {
// if ( !pq.contains((long)(res[i] * h[j])) ) {
// pq.add( (long)( res[i] * h[j]) );
// }
// }
// if ( i+1 < n ) {
// res[i+1] = pq.poll();
// }
// }
// return (int)res[n-1];
//動態規劃三指針做法
int dp[] = new int[n];
dp[0] = 1;
int i2 = 0 , i3 = 0 , i5 = 0;
for( int i = 1 ; i < n ; i++ ) {
dp[i] = Math.min( dp[i2] * 2 , Math.min( dp[i3] * 3 ,
dp[i5] * 5 ));
if ( dp[i] == dp[i2] * 2 ) {
i2++;
}
if ( dp[i] == dp[i3] * 3 ) {
i3++;
}
if ( dp[i] == dp[i5] * 5 ) {
i5++;
}
}
return dp[n-1];
}
}