/*******************************************************************
Copyright(c) 2016, Tyrone Li
All rights reserved.
*******************************************************************/
// 作者:TyroneLi
//
/*
Q:
丑数:
把只包含因子2,3,5的数称为丑数,求按照从小到大的顺序的第1500个丑数。
习惯上我们把1当作是第一个丑数。
S:
1. 按照从1到第1500个丑数的顺序,逐个判断每个整数能不能只包含因子2,3,5;
一个整数如果包含因子2,那么可以被2连续整除;同理3,,5;最后被这三个
整肃连续整除的结果就是只剩下1。这种方法需要把非丑数的整肃也考虑进来,
时间效率不是很高。
2. 使用空间换时间的做法,一个丑数肯定是前面某个丑数的2,3,5倍,因此可以使用
这样的策略来求得后面一个丑数,假设已经有前面部分排序的丑数,那么可以有前面
某个丑数的2,3,5倍的数大于前面部分排序丑数最大的那个数的最小那个。因此我们
可以根据前面已经保存的丑数计算后面的丑数。
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
bool isUgly(int num)
{
while(num % 2 == 0)
num /= 2;
while(num % 3 == 0)
num /= 3;
while(num % 5 == 0)
num /= 5;
bool result = (num == 1)?true:false;
// std::cout << result << std::endl;
return result;
}
int uglyNum_slow(int uglyIndex)
{
if(uglyIndex <= 0)
return 0;
int num_idx =0;
int ugly_idx = 0;
while(ugly_idx < uglyIndex)
{
// std::cout << ugly_idx << std::endl;
// std::cout << num_idx << std::endl;
++num_idx;
if(isUgly(num_idx))
++ugly_idx;
}
return num_idx;
}
int min(int a, int b, int c)
{
int min = a<b?a:b;
return (min<c)?min:c;
}
int uglyNum(int uglyIndex)
{
if(uglyIndex <= 0)
return 0;
int*uglyNumsSeq = new int[uglyIndex];
int*ugly_2 = uglyNumsSeq;
int*ugly_3 = uglyNumsSeq;
int*ugly_5 = uglyNumsSeq;
uglyNumsSeq[0] = 1;
int uglyIdx = 1;
while(uglyIdx < uglyIndex)
{
int min_tmp = min(*ugly_2*2, *ugly_3*3, *ugly_5*5);
uglyNumsSeq[uglyIdx] = min_tmp;
while((*ugly_2)*2 <= uglyNumsSeq[uglyIdx]) ugly_2++;
while((*ugly_3)*3 <= uglyNumsSeq[uglyIdx]) ugly_3++;
while((*ugly_5)*5 <= uglyNumsSeq[uglyIdx]) ugly_5++;
++uglyIdx;
}
int ugly_rst = uglyNumsSeq[uglyIdx - 1];
delete[] uglyNumsSeq;
return ugly_rst;
}
void test_1()
{
std::cout << "Test 1" << std::endl;
for(int i = 0; i < 101; ++i)
std::cout << "1500th ugly number " << uglyNum(i) << std::endl;
for(int i = 0; i < 101; ++i)
std::cout << "1500th ugly number " << uglyNum_slow(i) << std::endl;
}
void test_2()
{
std::cout << "Test 2" << std::endl;
std::cout << "0 ugly number " << uglyNum(0) << std::endl;
std::cout << "1 ugly number " << uglyNum(1) << std::endl;
std::cout << "2 ugly number " << uglyNum(2) << std::endl;
std::cout << "3 ugly number " << uglyNum(3) << std::endl;
std::cout << "4 ugly number " << uglyNum(4) << std::endl;
std::cout << "5 ugly number " << uglyNum(5) << std::endl;
std::cout << "6 ugly number " << uglyNum(6) << std::endl;
std::cout << "0 ugly number " << uglyNum_slow(0) << std::endl;
std::cout << "1 ugly number " << uglyNum_slow(1) << std::endl;
std::cout << "2 ugly number " << uglyNum_slow(2) << std::endl;
std::cout << "3 ugly number " << uglyNum_slow(3) << std::endl;
std::cout << "4 ugly number " << uglyNum_slow(4) << std::endl;
std::cout << "5 ugly number " << uglyNum_slow(5) << std::endl;
std::cout << "6 ugly number " << uglyNum_slow(6) << std::endl;
}
void test_uglyNum()
{
test_1();
test_2();
}
int main(int argc, char**argv)
{
test_uglyNum();
return 0;
}