题目描述:
我们把只包含因子2、3和5的数称作丑数(Ugly Number)。
例如6、8都是丑数,但14不是,因为它包含因子7。
求第n个丑数的值。
样例
输入:5
输出:5
注意:习惯上我们把1当做第一个丑数。
分析:
方法一:
打表备查,将每个已经判断的丑数保存进哈希表,如果某数能被2,3,5之一整除且商为丑数,则该数为丑数。该方法缺点是内存消耗太大,超过了限制。如果在判断丑数的函数里返回m[n/2]之类的,空间会超过限制,如果返回count函数,时间也会超过限制,所以仅限于几百个以内的丑数的判断
class Solution {
public:
unordered_map<int,int> m;
int getUglyNumber(int n) {
int i,cnt = 0;
for(i = 1;i < 6;i++){
m[i] = 1;
cnt++;
if(cnt == n) return i;
}
while(1){
if(judge(i)) m[i]++,cnt++;
if(cnt == n) return i;
i++;
}
}
bool judge(int n){
if(n % 2 == 0) return m[n / 2];
if(n % 3 == 0) return m[n / 3];
if(n % 5 == 0) return m[n / 5];
return false;
}
};
方法二:
三指针法。先说下用的较少的vector的定义。
如果不提前定义vector的元素个数,之后会每次容量倍增的方式来拓展空间。
我们知道,丑数除了1一定是2,3,5的倍数,那么2的n倍,3的n倍,5的n倍也就是丑数的全集了。第一个丑数为1,那么接下的丑数就是1的2,3倍,1的二倍加入后,指针应该后移移到2,2的2被小于1的五倍,所以3之后还是要放进4.可能描述比较模糊,具体过程参考代码即可,类似于三路归并排序,从2,3,5的倍数组成的三个序列中每次挑出新的最小元素加入。
分析下过程:
向量q中,初始为1,先加入2,i++,再加入3,j++,加入4,i++,加入5,k++,加入6,i++,j++。可以看到,当加入的数是几个因子的倍数时,对应的指针都会++。
class Solution {
public:
int getUglyNumber(int n) {
vector<int> q(1,1);
int i = 0,j = 0,k = 0;
while(--n){
int t = min(q[i]*2,min(q[j]*3,q[k]*5));
q.push_back(t);
if(q[i] * 2 == t) i++;
if(q[j] * 3 == t) j++;
if(q[k] * 5 == t) k++;
}
return q.back();
}
};