class Solution {
public int nthUglyNumber(int n) {
int a = 1;
int b = 1;
int c = 1;
int[] dp = new int[n+1];//dp[i]表示第i个丑数
dp[1] = 1;
for(int i=2;i<=n;i++){
dp[i] = Math.min(Math.min(dp[a]*2,dp[b]*3),dp[c]*5);
if(dp[i]==dp[a]*2){
a++;
}
if(dp[i]==dp[b]*3){
b++;
}
if(dp[i]==dp[c]*5){
c++;
}
}
return dp[n];
}
}
之前对于动归的思路有点太狭隘了,一直以为是i和i-1之间的关系,这个题状态转移方程是这样的,挺好。
时间复杂度:O(n)
空间复杂度:O(n)
共以下 10 个回答
打卡
class Solution {
public int nthUglyNumber(int n) {
int a = 1, b = 1, c = 1;
int[] dp = new int[n+1];
dp[1] = 1;
for(int i=2; i<=n; i++){
dp[i] = Math.min(dp[a]2, Math.min(dp[b]3, dp[c]5));
if(dp[i] dp[a]2) a++;
if(dp[i] dp[b]3) b++;
if(dp[i] dp[c]5) c++;
}
}
时间:O(n);
空间:O(n)
class Solution {
public int nthUglyNumber(int n) {
int[] dp = new int[n];
int i = 0, j = 0, k = 0;
dp[0] = 1;
int current = 1;
while(current < n){
int min = Math.min(dp[i] * 2,Math.min(dp[j] * 3,dp[k] * 5));
dp[current++] = min;
if(min dp[i] * 2) i++;
if(min dp[j] * 3) j++;
if(min dp[k] * 5) k++;
}
return dp[n-1];
}
//时间复杂度On 空间复杂度On
时间复杂度$O(n)$,空间复杂度$O(n)$
时间复杂度:O(n)
空间复杂度:O(n)
class Solution { dp(n + 1, 1);
public:
int nthUglyNumber(int n) {
vector
int p2 = 1, p3 = 1, p5 = 1;
for(int i = 2; i <= n; i ++) {
int n2 = dp[p2] * 2, n3 = dp[p3] * 3, n5 = dp[p5] * 5;
dp[i] = min(min(n2, n3), n5);
if(dp[i] n2) p2 ++;
if(dp[i] n3) p3 ++;
if(dp[i] n5) p5 ++;
}
return dp[n];
}
};
时空均为n
时间复杂度O(n),空间复杂度O(1)
思路:从 1 开始,每个数都需要乘以 2,3,5;则使用三个变量来分别标记该数是否乘以对应数字,比如 a 表示 dp[a] 之前的 dp[0] … dp[a-1] 都乘以2了,b 表示 dp[b] 之前的 dp[0]…dp[b-1] 都乘以3了,c 表示 dp[0]…dp[c-1]都乘以5了,因此,当前的最小丑值应该在 dp[a]2, dp[b]3, dp[c]*5 中得出。
“`c++ dp(n);
class Solution {
public:
int nthUglyNumber(int n) {
vector
dp[0] = 1;
int a = 0, b = 0, c = 0;
for (int i=1; i