剑指Offer-49-丑数/力扣-264-丑数-Ⅱ
直达链接
从1开始遍历判断
书上给出了两个解法,1是很简单直接的遍历,从1开始判断每个数是不是“丑数”并计数,直到指定的n返回
bool isUglyNumber(int n) {
while (n % 2 == 0) n /= 2;
while (n % 3 == 0) n /= 3;
while (n % 5 == 0) n /= 5;
if (n == 1) return true;
return false;
}
int nthUglyNumber(int n) {
if (n <= 0) return 0;
int num = 1;
int uglyNum = 0;
while (uglyNum < n) {
num++;
if (isUglyNumber(num)) uglyNum++;
}
return num;
}
结果是859963392
,但是很明显会超时,我控制台等输出都等了快10s
动态规划,顺序生成并保存丑数序列
书上的解法2是按序生成“丑数”并保存在一个数组中,其实看解释的时候感觉不是很看的明白,但是看力扣的题解的恍然大悟,这不就是动态规划吗
在想能不能写完之后做空间优化,似乎是不能空间优化的……
- 为什么它这里的指针只是+1?+1之后的指向并不是当前index指向生成的最小元素呀
- 这里的三个if不能加else,为什么?
class Solution {
public:
int nthUglyNumber(int n) {
vector<int> dp(n);
dp[0] = 1;
int p2 = 0,p3 = 0,p5 = 0;
for (int i = 1; i < n; ++i) {
int num2 = dp[p2] * 2, num3 = dp[p3] * 3, num5 = dp[p5] * 5;
// 这里min函数只接受2个参数之间的比较
dp[i] = min(min(num2,num3),num5);
if (dp[i] == num2) p2++;
if (dp[i] == num3) p3++;
if (dp[i] == num5) p5++;
}
return dp[n-1];
}
};
不要快太多
时间和空间复杂度都是O(N),需要生成并保存n个数(长度为n的数组空间)