题目
我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。
思路
难点:不能漏掉某个丑数(在已有的丑数序列上每一个数都必须乘2, 乘3, 乘5, 这样才不会漏掉某些丑数)且要保证排列是有序的(假设已有的丑数序列为[1, 2, 3, ..., n1, n2],
如果单纯的让每个丑数乘2
, 乘3, 乘5
顺序排列的话肯定会有问题)
设置三个指针a,b,c
,分别记录前几个数已经被乘2
, 乘3
, 乘5
了,比如a
表示前(a-1)
个数都已经乘过一次2
了,下次应该乘2
的是第a
个数;b
表示前(b-1)
个数都已经乘过一次3
了,下次应该乘3
的是第b
个数;c
表示前(c-1)
个数都已经乘过一次5
了,下次应该乘5
的是第c
个数
java代码如下:
class Solution {
public int nthUglyNumber(int n) {
int[] dp = new int[n]; // 使用dp数组来存储丑数序列
dp[0] = 1; // dp[0]已知为1
int a = 0, b = 0, c = 0; // 下个应该通过乘2来获得新丑数的数据是第a个, 同理b, c
for(int i = 1; i < n; i++){
// n2表示通过第a个丑数乘2来得到的,n3表示通过第b个丑数乘3来得到的,同理n5
int n2 = dp[a] * 2, n3 = dp[b] * 3, n5 = dp[c] * 5;
dp[i] = Math.min(Math.min(n2, n3), n5);
if(dp[i] == n2){
a++; // 第a个数已经通过乘2得到了一个新的丑数,那下个需要通过乘2得到一个新的丑数的数应该是第(a+1)个数
}
if(dp[i] == n3){
b++; // 第 b个数已经通过乘3得到了一个新的丑数,那下个需要通过乘3得到一个新的丑数的数应该是第(b+1)个数
}
if(dp[i] == n5){
c++; // 第 c个数已经通过乘5得到了一个新的丑数,那下个需要通过乘5得到一个新的丑数的数应该是第(c+1)个数
}
}
return dp[n-1];
}
}