醜數

 

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

分析:

首先從醜數的定義我們知道,一個醜數的因子只有2,3,5,那麼醜數p = 2 ^ x * 3 ^ y * 5 ^ z,換句話說一個醜數一定由另一個醜數乘以2或者乘以3或者乘以5得到,那麼我們從1開始乘以2,3,5,就得到2,3,5三個醜數,在從這三個醜數出發乘以2,3,5就得到4,6,10,6,9,15,10,15,25九個醜數,我們發現這種方法會得到重複的醜數,而且我們題目要求第N個醜數,這樣的方法得到的醜數也是無序的。那麼我們可以維護三個隊列:

(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

選擇三個隊列頭裏最小的數5加入醜數數組,同時將該最小的數乘以2,3,5放入三個隊列;

(5)醜數數組:1,2,3,4,5

乘以2的隊列:6,8,10,

乘以3的隊列:6,9,12,15

乘以5的隊列:10,15,20,25

選擇三個隊列頭裏最小的數6加入醜數數組,但我們發現,有兩個隊列頭都爲6,所以我們彈出兩個隊列頭,同時將12,18,30放入三個隊列;

實現思路:

我們沒有必要維護三個隊列,只需要記錄三個指針顯示到達哪一步;“|”表示指針,arr表示醜數數組;

(1)1

|2

|3

|5

目前指針指向0,0,0,隊列頭arr[0] * 2 = 2,  arr[0] * 3 = 3,  arr[0] * 5 = 5

(2)1 2

2 |4

|3 6

|5 10

目前指針指向1,0,0,隊列頭arr[1] * 2 = 4,  arr[0] * 3 = 3, arr[0] * 5 = 5

(3)1 2 3

2| 4 6

3 |6 9

|5 10 15

目前指針指向1,1,0,隊列頭arr[1] * 2 = 4,  arr[1] * 3 = 6, arr[0] * 5 = 5

int GetUglyNumber_Solution(int index) {
        //0~6的醜數是0~6自己
        if(index<=6)
            return index;
        
        int p2=0;//2的倍數的下標
        int p3=0;//3的倍數的下標
        int p5=0;//5的倍數的下標
        int ugly=1;//醜數初始值
        
        vector<int> ret;//存放醜數的vectotr
        ret.push_back(ugly);//第一個醜數尾插到數組中
        
        while(ret.size()<index)
        {
            ugly=min(ret[p2]*2, min(ret[p3]*3, ret[p5]*5));//下一個醜數取乘2,乘3,乘5隊列中的最小的一個
            ret.push_back(ugly);
            
            //看看是哪個入了數組了,將其對應的下標往後挪一下
            if(ret[p2]*2==ugly)
                p2++;
            if(ret[p3]*3==ugly)
                p3++;
            if(ret[p5]*5==ugly)
                p5++;
        }
        
        return ugly;

 

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