编写一个程序,找出第 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];
}
}