【劍指offer】面試題49. 醜數

解題思路

image.png
題目做了很久,看了很多解析都很迷惑,看到一位同學關於此題的評論,感覺很有道理,解釋也很清晰,特此和大家分享,我只是個搬運工,大家多感謝原作者。
sunrise。同學的評論
以下均節選自該同學的評論

醜數的排列肯定是1,2,3,4,5,6,8,10… 然後有一個特點是,任意一個醜數都是由小於它的某一個醜數2,3或者5得到的,那麼如何得到所有醜數呢? 現在假設有3個數組,分別是: A:{12,22,32,42,52,62,82,10*2…}

B:{13,23,33,43,53,63,83,103…}

C:{15,25,35,45,55,65,85,105…}

那麼所有醜數的排列,必定就是上面ABC3個數組的合併結果然後去重得到的,那麼這不就轉換成了三個有序數組的無重複元素合併的問題了嗎?而這三個數組就剛好是{1,2,3,4,>5,6,8,10…}乘以2,3,5得到的。

合併有序數組的一個比較好的方法,就是每個數組都對應一個指針,然後比較這些指針所指的數中哪個最小,就將這個數放到結果數組中,然後該指針向後挪一位。
此外,注意到ABC三個數組實際上就是ugly[]*2,ugly[]*3和ugly[]*5的結果,所以每次只需要比較A[i]=ugly[i]*2,B[j]=ugly[j]*3和C[k]=ugly[k]*5的大小即可。然後誰最小,就把對應的指針往後移動一個,爲了去重,如果三個指針所指的元素都是最小的元素,那麼這3個指針都要往後移動一個。

代碼

class Solution {
public:
	int nthUglyNumber(int n) {
		if (n <= 0) return 0;
		int count = 1;
		vector<int> saveUUglyNumbers(n);
		saveUUglyNumbers[0] = 1;//基礎醜數爲1
		int p2, p3, p5;//分別指向三個有序鏈表(現象)的首元素,A,B,C
		p2 = p3 = p5 = 0;
		//將醜數排序
		while (count < n)
		{
			saveUUglyNumbers[count] = min(min(saveUUglyNumbers[p2] * 2, saveUUglyNumbers[p3] * 3), saveUUglyNumbers[p5] * 5);
            //三個有序鏈表可能有相同元素,所以只要是最小的,都要移動指針
			if (saveUUglyNumbers[p2] * 2 == saveUUglyNumbers[count]) p2++;
			if (saveUUglyNumbers[p3] * 3 == saveUUglyNumbers[count]) p3++;
			if (saveUUglyNumbers[p5] * 5 == saveUUglyNumbers[count]) p5++;
			count++;
		}
		return saveUUglyNumbers[count-1];
	}
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章