丑数:质因数只有质数的数
问题一:判断一个数是否为丑数
直接除就好,因为一个数连乘or连除是logn的,根本不怕。
class Solution {
public:
bool isUgly(int n) {
if(n == 0)return false;
while(n%2 == 0)n /= 2;
while(n%3 == 0)n /= 3;
while(n%5 == 0)n /= 5;
return n==1;
}
};
问题二:找第n个丑数
这个就稍微有点难了,因为乘法顺序很多,用数学规律是不太能做的。
有一个点很重要,当我们判断第i个数是不是丑数,其实要让前面已经计算过的乘以可能的质因数。考虑最长上升子序列的做法,可以得到一个
O
(
N
2
)
O(N^2)
O(N2)的算法。
但我们很快会发现,这也太多重复计算了,还得存个数组记录存过的数。所以就想到了指针法,每个质因数分配一个指针,指向位置前面的数都是乘过的(后面不可能再出现)。因此,我们每次只需要比较每个指针指向的位置,就可以避免所有重复的数。
class Solution {
public:
int nthUglyNumber(int n) {
vector<int> factors{2, 3, 5};
vector<int> dp(3, 1);
vector<int> ugly(n+1);
ugly[1] = 1;
for(int i=2;i<=n;i++)
{
ugly[i] = ugly[dp[0]]*factors[0];
for(int j=1;j<3;j++)
ugly[i] = min(ugly[i], ugly[dp[j]]*factors[j]);
for(int j=0;j<3;j++)
{
if(ugly[i] == ugly[dp[j]]*factors[j])dp[j]++;
}
}
return ugly[n];
}
};