题目描述
把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
方法一、遍历判断。
依次判断每个数字是不是丑数,如果一个数是丑数,那么他将只能够被2、3、5所整除。
bool isUgly(int n){
while(n % 2 == 0){
n /= 2;
}
while(n % 3 == 0){
n /= 3;
}
while(n % 5 == 0){
n /= 5;
}
return (n ==1) ? true : false;
}
class Solution {
public:
int GetUglyNumber_Solution(int index) {
if (index <=0)
return 0;
int n = 0;
int ret = 0;
while( n < index){
++ret;
if(isUgly(ret)){
++n;
}
}
return ret;
}
};
但是这种方法对每一个数字都要进行判断,时间复杂度较高。
方法二、根据丑数生成的规律生成按顺序排列的丑数。
把前几位的丑数列举出来:1、2、3、4、5、6、8、9、10、12、15、16……
根据定义和观察可知,每个丑数都是前面的丑数乘以2或3或5生成的。为了满足由小到大的顺序,前面一个丑数分别乘以2,3,5后,取其中的最小值加入到丑数的数列中。同时乘了几,那个标志位相应后移。
int min(int a, int b, int c){
int min = (a<b) ? a:b;
return (min < c) ? min:c;
}
class Solution {
public:
int GetUglyNumber_Solution(int index) {
if(index < 7) return index; //根据枚举出的前6个数可知
vector<int> ret(index);
ret[0] = 1;
int t2=0, t3=0, t5=0; //开始时3个“指针”都指向1
for(int i=1; i<index; ++i){
ret[i] = min(ret[t2]*2, ret[t3]*3, ret[t5]*5); //取最小值
if(ret[i] == ret[t2]*2) t2++; //相应的“指针”后移
if(ret[i] == ret[t3]*3) t3++;
if(ret[i] == ret[t5]*5) t5++;
}
return ret[index-1];
}
};
这种方法开辟了新的vector,达到用空间换时间的目的。