题目: 我们把只包含因子2,3和5的数乘坐丑数(Ugly Nunber),求按从小到大的顺序的第1500个丑数。例如:6和8是丑数,但14不是丑数,因为它包含因子7。习惯上我们把1当作第一个丑数。
常规方案:逐个判断每个整数是不是丑数
丑数的定义是只能被2,3,5整除,所以一个整数如果能被2整除,就连续除以2;能被3整除,就连续除以3;能被5整除,就连续除以5。如果最后得到的是1,那么这个数就是丑数。
根据以上思路,我们得到了一个常规解法:
def isUgly(number):
while(number%2==0):
number/=2
while(number%3==0):
number/=3
while(number%5==0):
number/=5
return [False,True][number==1]
def getUglyNumber1(index):
if index<0:
return 0
number=0
uglyfound=0
while(uglyfound<index):
number+=1
if isUgly(number):
uglyfound+=1
return number
常规解法比较容易理解,但是需要每一个整数都参与判断是否为丑数,大大增加了时间消耗,我们可以对以上解法进行优化,通过一定的空间消耗来换取时间效率,也就是建立一个数组存放从小到大的每一个丑数,循环得到的直接就是丑数。
空间换时间方案:建立丑数数组
根据丑数的定义,一个丑数只包含2,3,5的因子,所以当我们有了一些按顺序排列较小的丑数的时候,并且这些丑数中最大的记为m,分别把这些丑数乘以2,3,5,得到的最小的大于m的值即为要加入丑数数组的下一个值。因为丑数数组已经排序,所以我们可以在循环中更新需要计算乘以2,或者3,或者5的丑数的位置,直到找到题目所求的丑数。
代码如下:
def getUglyNumber2(index):
if index<0:
return 0
pUglyNumbers=[1]*index
nextUglyIndex=1
pMultiply2=0
pMultiply3 = 0
pMultiply5 = 0
while(nextUglyIndex<index):
minn=min(pUglyNumbers[pMultiply2]*2,pUglyNumbers[pMultiply3]*3,pUglyNumbers[pMultiply5]*5)
pUglyNumbers[nextUglyIndex]=minn
while(pUglyNumbers[pMultiply2]*2<=pUglyNumbers[nextUglyIndex]):
pMultiply2+=1
while (pUglyNumbers[pMultiply3] * 3 <= pUglyNumbers[nextUglyIndex]):
pMultiply3 += 1
while (pUglyNumbers[pMultiply5] * 5 <= pUglyNumbers[nextUglyIndex]):
pMultiply5 += 1
nextUglyIndex+=1
return minn
当指定取第1500个丑数时候,两种方法的时间消耗对比如下:
当然方法2如果用C或者C++的话,pMutiply2,pMutiply3,pMutiply5的指标可以用指针来实现。
int Min(int number1, int number2, int number3);
int GetUglyNumber_Solution2(int index)
{
if(index <= 0)
return 0;
int *pUglyNumbers = new int[index];
pUglyNumbers[0] = 1;
int nextUglyIndex = 1;
int *pMultiply2 = pUglyNumbers;
int *pMultiply3 = pUglyNumbers;
int *pMultiply5 = pUglyNumbers;
while(nextUglyIndex < index)
{
int min = Min(*pMultiply2 * 2, *pMultiply3 * 3, *pMultiply5 * 5);
pUglyNumbers[nextUglyIndex] = min;
while(*pMultiply2 * 2 <= pUglyNumbers[nextUglyIndex])
++pMultiply2;
while(*pMultiply3 * 3 <= pUglyNumbers[nextUglyIndex])
++pMultiply3;
while(*pMultiply5 * 5 <= pUglyNumbers[nextUglyIndex])
++pMultiply5;
++nextUglyIndex;
}
int ugly = pUglyNumbers[nextUglyIndex - 1];
delete[] pUglyNumbers;
return ugly;
}
int Min(int number1, int number2, int number3)
{
int min = (number1 < number2) ? number1 : number2;
min = (min < number3) ? min : number3;
return min;
}