264.Ugly Number II(Medium)

Write a program to find the n-th ugly number.

Ugly numbers are positive numbers whose prime factors only include 2, 3, 5. For example, 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 is the sequence of the first 10 ugly numbers.

Note that 1 is typically treated as an ugly number.

Hint:

  1. The naive approach is to call isUgly for every number until you reach the n<sup style="box-sizing: border-box; position: relative; font-size: 12px; line-height: 0; vertical-align: baseline; top: -0.5em;">th one. Most numbers are not ugly. Try to focus your effort on generating only the ugly ones.
  1. An ugly number must be multiplied by either 2, 3, or 5 from a smaller ugly number.
  2. The key is how to maintain the order of the ugly numbers. Try a similar approach of merging from three sorted lists: L<sub style="box-sizing: border-box; position: relative; font-size: 12px; line-height: 0; vertical-align: baseline; bottom: -0.25em;">1, L<sub style="box-sizing: border-box; position: relative; font-size: 12px; line-height: 0; vertical-align: baseline; bottom: -0.25em;">2, and L<sub style="box-sizing: border-box; position: relative; font-size: 12px; line-height: 0; vertical-align: baseline; bottom: -0.25em;">3.
  3. Assume you have U<sub style="box-sizing: border-box; position: relative; font-size: 12px; line-height: 0; vertical-align: baseline; bottom: -0.25em;">k, the k<sup style="box-sizing: border-box; position: relative; font-size: 12px; line-height: 0; vertical-align: baseline; top: -0.5em;">th ugly number. Then U<sub style="box-sizing: border-box; position: relative; font-size: 12px; line-height: 0; vertical-align: baseline; bottom: -0.25em;">k+1 must be Min(L<sub style="box-sizing: border-box; position: relative; font-size: 12px; line-height: 0; vertical-align: baseline; bottom: -0.25em;">1 * 2, L<sub style="box-sizing: border-box; position: relative; font-size: 12px; line-height: 0; vertical-align: baseline; bottom: -0.25em;">2 * 3, L<sub style="box-sizing: border-box; position: relative; font-size: 12px; line-height: 0; vertical-align: baseline; bottom: -0.25em;">3 * 5).

  題意就不翻譯了,意思就是把丑數(shù)從小到大排列闪唆,輸出制定位置的那個(gè)丑數(shù)是多少盅粪,按照上一題的那種樸素判斷當(dāng)然是行得通的,只要把1~n的數(shù)全部都驗(yàn)證一遍悄蕾,自然可以找到第n個(gè)票顾,但是認(rèn)真想想,一旦n大了之后帆调,其實(shí)丑數(shù)的個(gè)數(shù)是不多的奠骄,也就是說驗(yàn)證成功的次數(shù)遠(yuǎn)遠(yuǎn)小于失敗的,所以用樸素的驗(yàn)證方式贷帮,顯然是相當(dāng)浪費(fèi)時(shí)間(事實(shí)上也是)戚揭,所以我們的思路就是想到如何一個(gè)一個(gè)計(jì)算出丑數(shù)诱告,找到其中的規(guī)律撵枢,主動(dòng)去計(jì)算丑數(shù)而不是被動(dòng)得驗(yàn)證是不是丑數(shù)

My Solution

(Java) Version 1 Time: 131ms:

  計(jì)算丑數(shù)的原理當(dāng)然不難,不要想到這一點(diǎn)還是花了不少功夫精居,首先每個(gè)丑數(shù)都是由2,3,5相乘得來的锄禽,而且每一個(gè)相同乘數(shù)的個(gè)數(shù)還不定,比如有5個(gè)5靴姿,3個(gè)1之類的沃但,所以只能從小到大一個(gè)一個(gè)算出來,然后我們又發(fā)現(xiàn)了每個(gè)丑數(shù)其實(shí)都是由前面小的丑數(shù)乘以2,3,5得來的佛吓,那就很明顯了宵晚,我們只要把前面的丑數(shù)都乘以2,3,5,然后結(jié)果里面最小的那個(gè)就一定是下一個(gè)丑數(shù)了

public class Solution {
    public int nthUglyNumber(int n) {
        int[] nums = new int[n];
        nums[0]=1;
        int max2=0,max3=0,max5=0,index;
        for(int i=0;i<n-1;i++){
            index=0;
            while(max2<=nums[i]){
                max2=nums[index]*2;
                index++;
            }
            index=0;
            while(max3<=nums[i]){
                max3=nums[index]*3;
                index++;
            }
            index=0;
            while(max5<=nums[i]){
                max5=nums[index]*5;
                index++;
            }
            nums[i+1]=max2<max3?max2<max5?max2:max5<max3?max5:max3:max3<max5?max3:max5;
        }
        return nums[n-1];
    }
}

(Java) Version 2 Time: 46ms (By luke.wang.7509):

  這個(gè)解法的生成形式和上一個(gè)并無不同维雇,不過上一個(gè)解法每一次都要從第一個(gè)丑數(shù)開始乘顯然是沒有必要的淤刃,因?yàn)橛泻芏嘀貜?fù),這里就避免了這個(gè)問題

public class Solution {
    public int nthUglyNumber(int n) {
        if(n<=0) return 0;
        int a=0,b=0,c=0;
        List<Integer> table = new ArrayList<Integer>();
        table.add(1);
        while(table.size()<n)
        {
            int next_val = Math.min(table.get(a)*2,Math.min(table.get(b)*3,table.get(c)*5));
            table.add(next_val);
            if(table.get(a)*2==next_val) a++;
            if(table.get(b)*3==next_val) b++;
            if(table.get(c)*5==next_val) c++;
        }
        return table.get(table.size()-1);
    }
}

(Java) Version 3 Time: 4ms (By TheKingRingReal):

  DFS是深度優(yōu)先的搜索算法吱型,這里我還沒能理解逸贾,不過從結(jié)果上看,已經(jīng)很顯然了……4ms快到媽都不認(rèn)得是誰
  作者的解釋:


we can get a tree like this which contains all the ugly number ;just use three point to dfs because of I can not find the relationship between three point ; so we can think it just like this picture

each point 3 and 5 can have the 2_3and 2_5;3_5 child.and we can use a tricky in programming that if we meet 2_3=6 we should p2++;p3++;if 3
5:p5++;p3++;just like the code writ in DFS function*

public class Solution {
    public int nthUglyNumber(int n) {
            int[] dp=new int[n];dp[0]=1;
            return DFS(dp,1,0,0,0,n);
    }

    private int DFS(int[] dp, int i, int p2, int p3, int p5, int n) {
        if (i==n)return dp[n-1];
        dp[i]=Math.min(dp[p2]*2, Math.min(dp[p3]*3,dp[p5]*5));
        if (dp[i]==dp[p2]*2)p2++;
        if(dp[i]==dp[p3]*3)p3++;
        if (dp[i]==dp[p5]*5)p5++;
        return DFS(dp, i+1, p2, p3, p5, n);
    }
}

(Java) Version 4 Time: 2ms (By zmajia):

  這個(gè)哈哈哈哈哈哈逗逼把測試樣例的極限試了出來,然后打表了哈哈哈哈哈哈铝侵,實(shí)在是太壞了灼伤,所以獲得了最快的速度,已知極限用打表的方式空間換時(shí)間還是很管用的

public class Solution {
        static int[] save = new int[3000];
        static int flag = 0;
        public int nthUglyNumber(int n) {
           if(flag == 0){
               flag ++;
               init();
           }
           return save[n-1];
        }
        public static void init(){
            int _2 = 0, _3 = 0, _5 = 0;
            save[0] = 1;
            for(int i = 1; i < 3000; i++){
                int min = Math.min(save[_2]*2, Math.min(save[_3]*3,save[_5]*5));
                if(save[_2]*2 == min) {
                    save[i] = save[_2]*2;
                    _2 ++;
                }
                if(save[_3]*3 == min) {
                    save[i] = save[_3]*3;
                    _3 ++;
                }
                if(save[_5]*5 == min) {
                    save[i] = save[_5]*5;
                    _5 ++;
                }
            }
        }
    }

(Java) Version 5 Time: 108ms (By saharH):

  TreeSet我沒有怎么研究過咪鲜,雖然慢但這是我看到的最簡潔的做法狐赡,其中起作用的應(yīng)該就是TreeSet的一些特性了,值得研究

public class Solution {
    public int nthUglyNumber(int n) {
        TreeSet<Long> hs = new TreeSet<>(Arrays.asList(1l, 2l, 3l, 5l));
        Long e = 1l;
        while( n != 0){
            e = hs.pollFirst();
            hs.add(e * 2);
            hs.add(e * 3);
            hs.add(e * 5);
            n--;
        }
        return e.intValue();
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末嗜诀,一起剝皮案震驚了整個(gè)濱河市猾警,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌隆敢,老刑警劉巖发皿,帶你破解...
    沈念sama閱讀 216,919評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異拂蝎,居然都是意外死亡穴墅,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門温自,熙熙樓的掌柜王于貴愁眉苦臉地迎上來玄货,“玉大人,你說我怎么就攤上這事悼泌∷勺剑” “怎么了?”我有些...
    開封第一講書人閱讀 163,316評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵馆里,是天一觀的道長隘世。 經(jīng)常有香客問我,道長鸠踪,這世上最難降的妖魔是什么丙者? 我笑而不...
    開封第一講書人閱讀 58,294評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮营密,結(jié)果婚禮上械媒,老公的妹妹穿的比我還像新娘。我一直安慰自己评汰,他們只是感情好纷捞,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,318評(píng)論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著被去,像睡著了一般主儡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上编振,一...
    開封第一講書人閱讀 51,245評(píng)論 1 299
  • 那天缀辩,我揣著相機(jī)與錄音臭埋,去河邊找鬼。 笑死臀玄,一個(gè)胖子當(dāng)著我的面吹牛瓢阴,可吹牛的內(nèi)容都是我干的成福。 我是一名探鬼主播脆粥,決...
    沈念sama閱讀 40,120評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼吠撮,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼隅很!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起遗遵,我...
    開封第一講書人閱讀 38,964評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤瘦材,失蹤者是張志新(化名)和其女友劉穎尸疆,沒想到半個(gè)月后臼膏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體硼被,經(jīng)...
    沈念sama閱讀 45,376評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,592評(píng)論 2 333
  • 正文 我和宋清朗相戀三年渗磅,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了嚷硫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,764評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡始鱼,死狀恐怖仔掸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情医清,我是刑警寧澤起暮,帶...
    沈念sama閱讀 35,460評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站会烙,受9級(jí)特大地震影響负懦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜持搜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,070評(píng)論 3 327
  • 文/蒙蒙 一密似、第九天 我趴在偏房一處隱蔽的房頂上張望焙矛。 院中可真熱鬧葫盼,春花似錦、人聲如沸村斟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蟆盹。三九已至孩灯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間逾滥,已是汗流浹背峰档。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人讥巡。 一個(gè)月前我還...
    沈念sama閱讀 47,819評(píng)論 2 370
  • 正文 我出身青樓掀亩,卻偏偏與公主長得像,于是被迫代替她去往敵國和親欢顷。 傳聞我的和親對(duì)象是個(gè)殘疾皇子槽棍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,665評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 背景 一年多以前我在知乎上答了有關(guān)LeetCode的問題, 分享了一些自己做題目的經(jīng)驗(yàn)。 張土汪:刷leetcod...
    土汪閱讀 12,744評(píng)論 0 33
  • 姐姐夏萱抬驴,天生心臟不好炼七,一直在治療中,大哥夏柯布持,成熟穩(wěn)重豌拙,對(duì)妹妹很溺愛。他們的爸爸夏安题暖,媽媽蘇晴是一對(duì)顏值很高的...
    smile竹閱讀 316評(píng)論 0 0
  • 2017年7月11日姆蘸,多云,天使助殘服務(wù)團(tuán)隊(duì)于11:25接到家住西華北區(qū)6幢4單元203行動(dòng)不便的殘疾人杜玉昆電話...
    C11閱讀 193評(píng)論 0 0
  • 悵望灰天月何在, 就似君影無痕灌侣, 叫人捉摸不透推捐, 還生明, 寂如花侧啼, 香如子牛柒, 湘妃一舞天涯, 悔之痊乾, 泣涕之皮壁, ...
    Ulia閱讀 215評(píng)論 0 13
  • 愛上一個(gè)人后有些歌會(huì)不忍聽,因?yàn)楦柙~暗含著心情哪审,有些話不敢說蛾魄,因?yàn)橹谎云Z就能勾起往事,想起以后湿滓,心里就有那種...
    木東木東閱讀 712評(píng)論 11 7