剑指offer面试题34

面试题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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值