Leetcode練習 #264 Ugly Number II




題目簡析:題目要求找出第N個醜陋數,根據醜陋數的特點,醜陋數只有因數2 3 5,因此當N到達一定數字時,醜陋數的大小會非常大,因此這道題目需要思考一個時間複雜度比較低的算法。

       我的第一個算法是,維護一個包含特殊數字的數組A,從num=1開始,假如這個num滿足以下條件,那麼就放到數組A裏,反之則放到醜陋數B中:

(1)  num既不能被2,也不能被3、5整除

(2)  假如能被2、3、5三者其中之一整除,整除後的商的數字在數組A中

同時,爲了使得在數組A中的檢索時間複製度達到極限O(1),我令A中所有數都是0,但是檢測到滿足(1)(2)的數組時,採用A[num]=-1的方式儲存數組,即犧牲非常大的空間來換取時間。但是,最後提交時,估計空間過大,因此不能通過。

換言之,在已有的數組中進行檢索,要麼空間複雜度過高,要麼時間複雜度過高(即使是二分查找O(log) ),所以要拋棄檢索這個環節。因此第二個算法就是,讓數組ugly={1},每次選擇一個符合條件的最小丑陋數依次加入。

根據醜陋數的特點,我們可以歸納爲,一個新的醜陋數是從已有的醜陋數中之一與2,3,5相乘所得,因此我們每一輪從三者選擇一個最小值就行。

       我們嘗試寫出三組醜陋數,分別是醜陋數序列(斜體數字) x 2 / 3 /5,如下

1*2    2*2    3*2    4*2    5*2……….

1*3    2*3    3*3    4*3    5*3……….

1*5    2*5    3*5    4*5    5*5……….

 

其中醜陋數序列爲 1 2  3  4 5  6  8 9  10 ……….

 

所以我們維護三個數組(或者隊列),每個數組分別有一個下標,每個下標表示這個數組的第幾個醜陋數,我們假設三個數組分別爲 g2,g3. g5  下標分別爲p2  p3  p5,以下我們模仿以下添加前幾個醜陋數,p2 p3 p5初始均爲0

第一輪:g2=0, g3=0, g5=0 àg2[p2]=2,g3[p3]=3, g5[P5]=5, 選取g2[p2]=2加入醜陋數,g2++

 

第二輪:g2=1, g3=0, g5=0 àg2[p2]=4,g3[p3]=3, g5[P5]=5, 選取g3[p3]=3加入醜陋數,g3++

 

第三輪:g2=1, g3=1, g5=0 àg2[p2]=4 g3[p3]=6,g5[P5]=5, 選取g2[p2]=4加入醜陋數,g2++

 

第四輪:g2=2, g3=1, g5=0 àg2[p2]=6, g3[p3]=6,g5[P5]=5, 選取g5[p5]=5加入醜陋數,g5++

 

第五輪:g2=2 g3=2, g5=21àg2[p2]=6, g3[p3]=6,g5[P5]=10, 選取g2[p2]=6加入醜陋數,g2++

 

 

補充的是,每組的醜陋數可以通過2*ugly[g2] 或者3*ugly[g3]  5*ugly[g5]獲取每組的下一個醜陋數,以及避免重複的醜陋數(比如2*3=6 和3*2=6),每一次添加醜陋數都要與上一個醜陋數對比,避免重複。

 

下面附上代碼

class Solution {
public:
    int nthUglyNumber(int n) {
        vector<int>group2={2};
        vector<int>group3={3};
        vector<int>group5={5};

        int p2=0;
        int p3=0;
        int p5=0;
        vector<int> ugly={1};

        
        while(ugly.size()<=n){
            int min_num=min_ele(group2[p2],min(group3[p3],group5[p5]));
            
            if(ugly[ugly.size()-1]!=min_num)
                ugly.push_back(min_num);

            if(group2[p2]==min_num){

                group2.push_back(2*ugly[++p2]);
          
            }
            else if(group3[p3]==min_num){

                group3.push_back(3*ugly[++p3]);
                          
            }
            else if(group5[p5]==min_num){
                
                group5.push_back(5*ugly[++p5]);
                         
            }
                
        }

        return ugly[n-1];
        
    }
    int min_ele(int num1, int num2){
        if(num1>num2)
            return num2;

        return num1;
    }
    
    
};



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