题目描述
把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
思路1
对每个数字都判断该数字是不是丑数,然后返回第N个丑数即可。丑数的判断方法是:如果一个数字能被2整除,就连续除以2直到不能被2整除为止,如果此时该数字能被3整除,则连续除以3,直到不能被3整除为止,如果此时该数字能被5整除,则连续除以5,直到该数字不能被5整除为止,如果此时该数字为1,则原数字为丑数,否则不是丑数。代码如下:
class Solution {
public:
bool isUglyNumber(int number){ //判断number是否为丑数
while(number%2==0)
number /= 2;
while(number%3==0)
number /= 3;
while(number%5==0)
number /= 5;
if(number==1)
return true;
else return false;
}
int GetUglyNumber_Solution(int index) {
if(index==1)
return 1;
int i=1;
int j=2;
while(i<index){
if(isUglyNumber(j))
i++;
j++;
}
return j;
}
};
由于该算法对每个数字都要判断是否为丑数,时间复杂度过高,在牛客网上无法通过。
思路2
如果一个数是丑数,那么这个数乘以2、乘以3或者乘以5得到的结果也是丑数。因此,我们可以创建一个数组,里面是排序好的丑数,每一个丑数都是前面的丑数乘以2、3或5得到的。这种思路的难点在于如何保持该数组是排好序的。假设该数字目前的最大值是M,则M肯定是前面的某个丑数乘以2、3或5得到的。将前面的丑数乘以2时能得到若干小于等于M的结果,因为数组是排序的,这个结果已经存在于数组当中了,还会得到若干大于M的结果,我们将这个结果的最小值记为M2,同时记录计算出该结果的下标index2,下一次在计算时,不用从头开始计算了,只需从index2计算就行了。同样的,我们可以得到M3,M5,index3,index5。因为数组是排序的,所以下一个丑数是M2,M3,M5的最小值。代码如下:
class Solution {
public:
int GetUglyNumber_Solution(int index) {
int* uglyNums = new int[index];
uglyNums[0] = 1;
int* multiply2 = uglyNums;
int* multiply3 = uglyNums;
int* multiply5 = uglyNums;
int nextUglyIdx = 1;
while(nextUglyIdx<index){
int minUglyNum = getMin(*multiply2*2, *multiply3*3, *multiply5*5);
uglyNums[nextUglyIdx] = minUglyNum;
while(*multiply2*2<=minUglyNum)
multiply2++;
while(*multiply3*3<=minUglyNum)
multiply3++;
while(*multiply5*5<=minUglyNum)
multiply5++;
nextUglyIdx++;
}
int ans = uglyNums[index-1];
delete[] uglyNums;
return ans;
}
int getMin(int num1, int num2, int num3){
int minNum = (num1<num2)? num1:num2;
minNum = (minNum<num3)? minNum:num3;
return minNum;
}
};