劍指offer(三十三)——醜數

劍指offer(三十三)——醜數

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

題解
理解題意很重要,咋一看會感覺醜數很複雜,但實際上你把它列出來就會發現,醜數定義是比較簡單的。1、2、3、4、5、6、8、9、10、12、15、18、20、25……仔細琢磨就會發現

  • 2=1*2
  • 3=1*3
  • 5=1*5
  • 4=2*2
  • 6=2*3
  • 10=2*5
  • 6=3*2
  • 9=3*3
  • 15=3*5
  • ……
    可以看出來醜數都是由醜數相乘得來的。在知道了定義之後我們能做什麼?這裏有一位大佬的解釋就很清楚。

鏈接:https://www.nowcoder.com/questionTerminal/6aa9e04fc3794f68acf8778237ba065b?f=discussion
來源:牛客網

維護三個隊列:
(1)醜數數組: 1
乘以2的隊列:2
乘以3的隊列:3
乘以5的隊列:5
選擇三個隊列頭最小的數2加入醜數數組,同時將該最小的數乘以2,3,5放入三個隊列;
(2)醜數數組:1,2
乘以2的隊列:4
乘以3的隊列:3,6
乘以5的隊列:5,10
選擇三個隊列頭最小的數3加入醜數數組,同時將該最小的數乘以2,3,5放入三個隊列;
(3)醜數數組:1,2,3
乘以2的隊列:4,6
乘以3的隊列:6,9
乘以5的隊列:5,10,15
選擇三個隊列頭裏最小的數4加入醜數數組,同時將該最小的數乘以2,3,5放入三個隊列;
(4)醜數數組:1,2,3,4
乘以2的隊列:6,8
乘以3的隊列:6,9,12
乘以5的隊列:5,10,15,20

這樣看思路是不是比較明朗了?但是3個隊列就顯得比較麻煩,所以我們用3個指針也可以達到相同的效果。
在這裏插入圖片描述

  • p1、p2、p3三個指針用來取代隊列的作用,由於默認1是醜數數組的第一位,所以先讓指針指向醜數數組list[0],分別乘上2、3、5,結果中最小的便是下一位醜數,這裏是2。
    在這裏插入圖片描述
  • 將2存入list中,並移動指針p1,然後重複乘上2、3、5,結果最小即是下一位醜數。在這裏插入圖片描述在這裏插入圖片描述
  • 這樣便可以求出題目所要求的數了。
public int GetUglyNumber_Solution(int index) {
		if (index < 7) {
			return index;
		}
		ArrayList<Integer> list = new ArrayList<>();
		list.add(1);
		int i, p1 = 0, p2 = 0, p3 = 0;
		for(i = 1; i < index; i++) {
			int mulTwo = list.get(p1) * 2;
			int mulThr = list.get(p2) * 3;
			int mulFiv = list.get(p3) * 5;
			int minNum = Math.min(mulTwo, Math.min(mulThr, mulFiv)); 
			list.add(minNum);
			if (minNum == mulTwo) {
				p1++;
			}
			if (minNum == mulThr) {
				p2++;
			}
			if (minNum == mulFiv) {
				p3++;
			}
		}
        return list.get(index - 1);
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章