丑数是指因子只有2,3,5的数字,特别的1被认为是丑数;寻找第1500个丑数按照一般的思路就是,暴力模拟,不断的用循环变量去除以2,3,5;如果能除尽就让计数器++;直到计数器==1500,就输出这个值;这样做确实可以但是会很浪费时间
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
using namespace std;
int ugly(int);
int main ()
{
int cnt=0;
int res;
for (int i=1;cnt!=1500;i++)
{
if (ugly(i))
{
res = i;
cnt++;
}
}
cout << res;
return 0;
}
int ugly (int num)
{
int flag=0;
while(num)
{
while(num%2==0) num/=2;
while(num%3==0) num/=3;
while(num%5==0) num/=5;
//如果是丑数的话到最后num的值一定是1;
if(num==1)
{
flag=1;
break;
}
else
{
flag=0;
break;
}
}
return flag;
}
我的电脑上花了有16秒QAQ,timelimted的既视感有没有,接下来就要开始优化了(这个思路也是我在网上看的觉得很好想写下来,绝对不是复制过来的 ,侵删)
丑数的因子只有2,3,5之后的丑数一定是当前的丑数乘以2,3,5后最小的并且是不重复的那个;
那么关键点来了:构造三个队列,分别放入2,3,5,然后寻找最小值,把队前的与最小值相同的数据出队并删除,然后再给后面的包括本身在内的队列入队一个元素(如果给所有的队列都入队元素会出现同的队列内存在相同的元素);元素是:出队元素乘以这个队列最开始的值(2,3,5)
用数据描述就是
有三个队列 n1 n2 n3;初始放入元素2,3,5
定义 minval;
n1 : 2
n2 : 3
n3 : 5
minval = 2;
第一次
n1 : 4
n2 : 3 6
n3 : 5 10
minval = 3;
第二次
n1 : 4 8
n2 : 6 12
n3 : 5 10 20
minval = 4;
…
一直这样循环下去,minval的值就是丑数,可以用一个数组保存下来,也可以直接搞一个计数器等到了第1500个的时候直接输出就好了
#include<iostream>
#include<stack>
#include<queue>
#include<cstdio>
#include<algorithm>
using namespace std;
int find_ugly_number (int n);
int main ()
{
int num = find_ugly_number(1500);
printf ("The 1500'th ugly number is <%d>.",num);
}
int find_ugly_number (int n)
{
if (n==1) return 1;
queue <int > q1,q2,q3;
int minval;
q1.push(2);
q2.push(3);
q3.push(5);
while (n-- > 1)
{
minval = min (min(q1.front(),q2.front()),q3.front());
//cout << minval << ' ';
if (minval == q1.front())
{
q1.pop();
q1.push(minval*2);
q2.push(minval*3);
q3.push(minval*5);
}else if (minval == q2.front())
{
q2.pop();
q2.push(minval*3);
q3.push(minval*5);
}
else
{
q3.pop();
q3.push(minval *5);
}
}
return minval;
}
暴力解决的时间16秒,用上数据结构和算法后时间只有0.02秒,这就输算法的魅力
最后在放一个水过的方法
题目不是让输出第1500个丑数么,直接暴力模拟,求出答案,写在源代码是直接cout<<"859963392";
多简单 QAQ;