题目描述
把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
思路(最优法为空间换时间)
尽量减少排序数组中已有的丑数的多余计算,只找刚好大于原数组中最大丑数的那个丑数(选择*2,*3,*5中最小的那个丑数为min)并记录
定义了三个指针分别各自向前移动,作*2,*3,*5操作,每次找到刚好大于当前丑数数组中最大的那个丑数的那个丑数作为下一个新的丑数(以此避免了对所有丑数都分别*2,*3,*5,减少了计算次数)
前20个丑数为:1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24, 25, 27, 30, 32, 36
注意:二级循环判断条件要有等号,否则可能出现重复的丑数
代码
class Solution {
public:
int GetUglyNumber_Solution(int index) {
//检验有效性
if(index <= 0)
return 0;
//
int* pUglyNumbersArray = new int[index];
//第一个丑数为1
pUglyNumbersArray[0] = 1;
//下一个丑数的索引
int nextUglyNumIndex = 1;
//初始化书中的T2, T3, T5从丑数数组首开始
int* pMultiply2 = pUglyNumbersArray;
int* pMultiply3 = pUglyNumbersArray;
int* pMultiply5 = pUglyNumbersArray;
while(nextUglyNumIndex < index)
{
//声明变量保存最新的丑数
int min = minOf3Number(*pMultiply2 * 2, *pMultiply3 * 3, *pMultiply5 * 5);
pUglyNumbersArray[nextUglyNumIndex] = min;
//更新T2, T3, T5使他们刚好大过此时丑数数组中最大的丑数
//注意循环判断条件要有等号,否则可能出现重复的丑数
while(*pMultiply2 * 2 <= pUglyNumbersArray[nextUglyNumIndex])
pMultiply2++;
while(*pMultiply3 * 3 <= pUglyNumbersArray[nextUglyNumIndex])
pMultiply3++;
while(*pMultiply5 * 5 <= pUglyNumbersArray[nextUglyNumIndex])
pMultiply5++;
++nextUglyNumIndex;
}
//保存所求丑数
int result = pUglyNumbersArray[nextUglyNumIndex - 1];
delete[] pUglyNumbersArray;
return result;
}
private:
int minOf3Number(int num1, int num2, int num3)
{
int min = (num1 < num2)? num1 : num2;
min = (min < num3)? min : num3;
return min;
}
};