lintcode 中等題:Ugly Numbers 醜數

來源:互聯網
上載者:User

標籤:

題目

醜數 

設計一個演算法,找出只含素因子3,5,7 的第 k 大的數。

合格數如:3,5,7,9,15......

範例

如果k=4, 返回 9

挑戰

要求時間複雜度為O(nlogn)或者O(n)

解題

法一:直接暴力,逐次判斷一個數是不是醜數

下面只對其中的奇數判斷是否是醜數,加不加奇數都逾時。

 

class Solution {    /**     * @param k: The number k.     * @return: The kth prime number as description.     */    public long kthPrimeNumber(int k) {        // write your code here        int i = 0;        int num = 3;        while( i < k){            if(isUgly(num)){                i++;            }            num += 2;        }        return num - 2;    }    public boolean isUgly(long num){        while(num%3 == 0){            num = num/3;        }        while(num%5 ==0){            num = num/5;        }        while(num%7==0){            num = num/7;        }        return num==1;    } };

法二:直接求醜數

參考連結

最小的連續三個醜數是:3,5,7.以後的每個醜數其因子也只能是3 5 7 那麼我們就可以看作:每個醜數可以寫成num = 3i* 5j*7k   ,每個醜數也一定是其前面的醜數乘以 3 或5 或7 得到的數,這樣我們可以以3 5 7 作為醜數的基數數組,這個醜數數組中的每個數分別乘以 3, 5, 7,得到三個醜數數組,當然其中也一定會有重複的,選取不在原醜數數組中的最小的那個數,加入的醜數數組中,醜數數組的元素就增加一個。

問題是:對三個數字,如何分別找乘以3 5 7 的最小值?

假設先找乘以3 的最小值,由於原始醜數數組是有序的,則第一個不在醜數數組中的那個數字就是最小的,對於 5 7 同理,第一個不在醜數數組中的那個數就是最小的醜數,或者說是第一個大於所有醜數的那個數就是最小的醜數,這樣,我們就找到了三個醜數。最小的醜數加入的醜數數組中。

class Solution {    /**     * @param k: The number k.     * @return: The kth prime number as description.     */    public long kthPrimeNumber(int k) {        // write your code here        long u[] = new long[k+1];        u[0] = 1;        int index = 1;        int i1 = 0,i2 = 0,i3 = 0;        long MIN = 0;        while(index <= k){            MIN = Math.min(u[i1] * 3 ,Math.min(u[i2] * 5,u[i3] * 7));            u[index++] = MIN;            i1 = 0;            i2 = 0;            i3 = 0;            while( u[i1] *3 <= MIN){                i1++;            }            while(u[i2] *5 <= MIN){                i2++;            }            while(u[i3] *7 <= MIN){                i3++;            }        }        return u[k];    }};
Java Code

總耗時: 752 ms

但是通過上面程式中,每次都要遍曆一遍醜數數組,時間複雜度比較長,但是也竟然AC了,同時裡面重讀的數也很多。我們可以記錄中間的某個醜數的下標 ui來實現,現在其之前的數乘以3都會小于于最大的醜數,其之後的數乘以3都大於最大的醜數。5 7 同理。這樣,我們可以在原先找到的滿足最小大於醜數數組最大值的那個原始的下標來考慮。

設 3 5 7對應的下標是:i1  i2 i3 這裡的下標意思:u[i1]*2是第一個大於最大丑數數組最大值的數。i1 i2 i3 可以理解為不同步的三個指標

當 i1是三個最小丑數中的最小值,則u[i1]*3 加入到醜數數組中,u[i1]*3 就是當前醜數數組的最大值,同時i1+=1 這裡進行加1 處理,因為其i1之前的數乘以2的值一定小於u[i1]*3 ,並且這個元素已經在醜數數組u中了,u[i1 + 1] * 3 也就是第一個大於醜數數組最大值的數組。此時對於  i2 i3 不做處理。其他情況類似。

 

class Solution {    /**     * @param k: The number k.     * @return: The kth prime number as description.     */    public long kthPrimeNumber(int k) {        // write your code here        long u[] = new long[k+1];        u[0] = 1;        int index = 1;        int i1 = 0,i2 = 0,i3 = 0;        long MIN = 0;        while(index <= k){            MIN = Math.min(u[i1] * 3 ,Math.min(u[i2] * 5,u[i3] * 7));            u[index++] = MIN;            if(MIN == u[i1] * 3){                i1 += 1;            }            if(MIN == u[i2] * 5){                i2 +=1;            }            if(MIN == u[i3] * 7){                i3 +=1;            }        }        return u[k];    }};
Java Code

 

總耗時: 1241 ms

 

 用ArrayList

class Solution {    /**     * @param k: The number k.     * @return: The kth prime number as description.     */    public long kthPrimeNumber(int k) {        // write your code here        int i1 = 1;        int i2 = 1;        int i3 = 1;        List<Long> list = new ArrayList<Long>();                list.add((long)1);        while(list.size() <= k){            long u1 = list.get(i1-1) * 3;            long u2 = list.get(i2-1) * 5;            long u3 = list.get(i3-1) * 7;            long min = Math.min(u1,Math.min(u2,u3));            if(min == u1)                i1++;            if(min == u2)                i2++;            if(min == u3)                i3++;            list.add(min);        }                return (long)list.get(k);    }};
Java Code

總耗時: 557 ms

class Solution:    """    @param k: The number k.    @return: The kth prime number as description.    """    def kthPrimeNumber(self, k):        # write your code here        i1 = 1        i2 = 1        i3 = 1        u = []        u.append(1)        while len(u) <= k:            u1 = u[i1 - 1] * 3            u2 = u[i2 - 1] * 5            u3 = u[i3 - 1] * 7            minu = min(u1,min(u2,u3))            if minu == u1:                i1 += 1            if minu == u2:                i2 += 1            if minu == u3:                i3 += 1            u.append(minu)        return u[k]
Python Code

總耗時: 108 ms

輸出第10個醜數的計算過程:

[1]-------------------3 5 7[1, 3]-------------------9 5 7[1, 3, 5]-------------------9 15 7[1, 3, 5, 7]-------------------9 15 21[1, 3, 5, 7, 9]-------------------15 15 21[1, 3, 5, 7, 9, 15]-------------------21 25 21[1, 3, 5, 7, 9, 15, 21]-------------------27 25 35[1, 3, 5, 7, 9, 15, 21, 25]-------------------27 35 35[1, 3, 5, 7, 9, 15, 21, 25, 27]-------------------45 35 35[1, 3, 5, 7, 9, 15, 21, 25, 27, 35]-------------------45 45 49[1, 3, 5, 7, 9, 15, 21, 25, 27, 35, 45]-------------------45

 

lintcode 中等題:Ugly Numbers 醜數

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.