问题
思路
只想到了朴素的思路,果然TLE。
参考了这篇链接。[ugly number ii]
其实,它的思路也很明显。和素数筛法差不多,这个可以叫做丑数筛法吧。
具体思路是这样,因为任何一个丑数的素因子只能是2,3,5.
所以,可以进一步知道,任何一个大的丑数,都是由小的丑数×2,3,5生成。所以,所有的丑数都是从1开始,然后乘以2,3,5生成。这个不是难点,难点是怎么样维护这个序列。
1 2 3
*2: 2 4 6
*3: 3 6 9
*5: 5 10 15
所以,难度在于怎么维护这个序列。参照的办法是利用三个列表的下表,分别向后走,因为不同的列表可能小的素数是不一样的,所以需要下标来区分他们。
其实,这个题的类似题目也给出了merge k lists这样的提示,所以需要这个的技巧。
代码
class Solution {
public:
int nthUglyNumber(int n) {
vector<int> ret;
ret.push_back(1);
int i2 = 0;
int i3 = 0;
int i5 = 0;
while(ret.size() < n){
int m2 = ret[i2]*2;
int m3 = ret[i3]*3;
int m5 = ret[i5]*5;
int tmp = min( m2, min(m3, m5) );
if( tmp == m2 ) ++i2;
if( tmp == m3 ) ++i3;
if( tmp == m5 ) ++i5;
ret.push_back(tmp);
}
return ret.back();
}
};