醜數 | 我們把只包含因子2、3和5的數稱作醜數。求按從小到大的順序的第1500個醜數。

面試題34:醜數

1.題目描述

我們把只包含因子2、3和5的數稱作醜數。求按從小到大的順序的第1500個醜數。例如6(6=3*2)、8(8=2*4,4=2*2)都是醜數,但14不是,因爲它包含因子7。習慣上我們把1當做第一個醜數。

2.題目分析

根據醜數的定義,醜數應該是另一個醜數乘以2、3或者5的結果(1除外)。因此我們可以創建一個數組,裏面的數字是排好序的醜數,每一個醜數都是前面的醜數乘以2、3或者5得到的。

這種思路的關鍵在於怎樣確保數組裏面的醜數是排好序的。假設數組中已經有若干個醜數排好序後存放在數組中,並且把已有最大的醜數記做M,我們接下來分析如何生成下一個醜數。該醜數肯定是前面某一個醜數乘以2、3或者5的結果,所以我們首先考慮把已有的每個醜數乘以2。在乘以2的時候能得到若干個小於或等於M的結果。由於是按照順序生成的,小於或者等於M肯定已經在數組中了,我們不需再次考慮;還會得到若干個大於M的結果,但我們只需要第一個大於M的結果,因爲我們希望醜數是按從小到大的順序生成的,其他更大的結果以後再說。我們把得到的第一個乘以2後大於M的結果記爲M2。同樣,我們把已有的每一個醜數乘以
3和5,能得到第一個大於M的結果M3和M5那麼下一個醜數應該是M2,M3和M5這3個數的最小者。

前面分析的時候,提到把已有的每個醜數分別都乘以2、3和5。事實上這不是必須的,因爲已有的醜數是按順序存放在數組中的。對乘以2而言,肯定存在某一個醜數T2,排在它之前的每一個醜數乘以2得到的結果都會小於已有最大的醜數,在它之後的每一個醜數乘以2得到的結果都會太大。我們只需記下這個醜數的位置,同時每次生成新的醜數的時候,去更新這個T2。對乘以3和5而言,也存在着同樣的T3和T5。

3.code

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)	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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章