题目
剑指 Offer 49. 丑数
我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。
示例
输入: n = 10
输出: 12
解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 个丑数。
说明:
- 1 是丑数。
- n 不超过1690。
题解
解法1:素数筛法+分解质因数
仅是一个思路,试了几个结果是正确的,但是运行会超时
#define Max 5000000
class Solution {
public:
vector<int>prime;
int isCom[Max]={0};
int nthUglyNumber(int n) {
findp();
int cnt=0;
for(int i=1;i<Max;i++)
{
if(i==1||i==2||i==3||i==5){
cnt++;
if(cnt==n)
return i;
}
int ugly=1;
if(isCom[i])
{
int bound=sqrt(i);
int tmp=i;
int j=0;
while(j<prime.size()&&prime[j]<=bound)
{
if(tmp%prime[j]==0)//是i的质因数
{
if(prime[j]!=2&&prime[j]!=3&&prime[j]!=5){
ugly=0;
break;
}
tmp/=prime[j];
}
else
j++;
}
//最后剩下质数
if(tmp!=1){
if(tmp!=2&&tmp!=3&&tmp!=5)
ugly=0;
}
//是丑数
if(ugly){
cnt++;
if(cnt==n)
return i;
}
}
}
return -1;
}
//筛素数
void findp()
{
for(int i=2;i<Max;i++)
{
if(isCom[i]==0)//质数
prime.push_back(i);
for(int j=0;j<prime.size()&&i*prime[j]<Max;j++)
{
isCom[i*prime[j]]=1;//标记合数
if(i%prime[j]==0)
break;
}
}
}
};
解法2:动态规划
这思路真的太妙了
class Solution {
public:
int nthUglyNumber(int n) {
int dp[1700];
dp[0]=1;
int a=0,b=0,c=0;
for(int i=1;i<n;i++)
{
int n2=dp[a]*2,n3=dp[b]*3,n5=dp[c]*5;
dp[i]=min(min(n2,n3),n5);
if(dp[i]==n2) a++;
if(dp[i]==n3) b++;
if(dp[i]==n5) c++;
}
return dp[n-1];
}
};