面试题34:丑数
题目:我们把只包含因子2、3和5的数称为丑数(Ugly Number)。求按从下到大的顺序的第1500个丑数。例如6,8都是丑数,当时14不是,因为它包含了因子7。习惯上我们把1当做第一个丑数。
预备知识:
为了优化时间性能,通常可以利用“以空间换取时间”。
其余%,0%2 也是0.
思路:
第一种思路:因为丑数可以被2,3,5整除,因此判断一个数是不是丑数,可以让他一直分别除2,3,5,直到最后为1.
这里有两种实现:
循环:
//判断一个数是否为丑数
bool IsUgly1(int number)
{
while(number % 2 == 0)
number /= 2;
while(number % 3 == 0)
number /= 3;
while(number % 5 == 0)
number /=5;
return (number == 1) ? true : false;
}
递归:
//判断数 number是否为丑数,递归实现
bool IsUgly2(int number)
{
bool flag = false;
if( number <= 0)
return false;
if(number == 1 || number == 2 || number == 3 || number == 5)
return true;
if( number % 2 == 0 || number % 3 == 0 || number % 5 == 0)
{
if (number % 2 == 0 )
{
flag = IsUgly2(number / 2);
return flag;
}
if (number % 3 == 0 )
{
flag = IsUgly2(number / 3 );
return flag;
}
if ( number % 5 == 0)
{
flag = IsUgly2(number / 5);
return flag;
}
}
return flag;
}
但是这种每次判断一个数是不是丑数的效率很低!!
第二种思路:可以先创建一个数组,把得到的丑数保存起来,并排好序,显然后面的丑数必然是前面的丑数乘以2,3,或5得到的。
算法实现:
// 面试题34.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <math.h>
//丑数
//判断一个数是否为丑数
bool IsUgly1(int number)
{
while(number % 2 == 0)
number /= 2;
while(number % 3 == 0)
number /= 3;
while(number % 5 == 0)
number /=5;
return (number == 1) ? true : false;
}
int GetUglyNumber_Solution1(int index)
{
if(index <= 0)
return 0;
int number = 0;
int uglyFound = 0;
while(uglyFound < index)
{
++number;
if(IsUgly1(number))
{
++uglyFound;
}
}
return number;
}
//求3个数中的最小值
int Min(int number1, int number2, int number3)
{
int min = (number1 < number2) ? number1 : number2;
min = (min < number3) ? min : number3;
return min;
}
int GetUglyNumber_Solution2(int index)
{
if(index <= 0) //处理特殊输入,如0
return 0;
int *pUglyNumbers = new int [index]; //pUglyNumber在栈上, new 的内存空间在堆上
pUglyNumbers[0] = 1; //习惯上认为1也是丑数
int nextUglyIndex = 1;
//定义了3个指针变量,指向同一内存区域块
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;
}
//判断数 number是否为丑数,递归实现
bool IsUgly2(int number)
{
bool flag = false;
if( number <= 0)
return false;
if(number == 1 || number == 2 || number == 3 || number == 5)
return true;
if( number % 2 == 0 || number % 3 == 0 || number % 5 == 0)
{
if (number % 2 == 0 )
{
flag = IsUgly2(number / 2);
return flag;
}
if (number % 3 == 0 )
{
flag = IsUgly2(number / 3 );
return flag;
}
if ( number % 5 == 0)
{
flag = IsUgly2(number / 5);
return flag;
}
}
return flag;
}
int GetUglyNumber_Solution3(int index)
{
if(index <= 0)
return 0;
int number = 0;
int uglyFound = 0;
while(uglyFound < index)
{
++number;
if(IsUgly2(number))
{
++uglyFound;
}
}
return number;
}
//*****************测试代码****************
void Test1()
{
int index = 14;
//printf("%d\t",GetUglyNumber_Solution1(index));
printf("\n*****************\n");
printf("%d\t",GetUglyNumber_Solution2(index));
printf("\n");
printf("\n*****************\n");
printf("%d\t",GetUglyNumber_Solution3(index));
printf("\n");
}
int _tmain(int argc, _TCHAR* argv[])
{
Test1();
return 0;
}