歡迎訪問我的博客:http://www.fupinyou.com
問題描述:
Write a program to find the nth super ugly number.Super ugly numbers are positive numbers whose all prime factors are in the given prime list primes of size k. For example, [1, 2, 4, 7, 8, 13, 14, 16, 19, 26, 28, 32] is the sequence of the first 12 super ugly numbers given primes = [2, 7, 13, 19] of size 4.
注意事項:
1 is a super ugly number for any given primes.The given numbers in primes are in ascending order.0 < k ≤ 100, 0 < n ≤ 10^6, 0 < primes[i] < 1000.
分析
題目大意就是說,超級丑陋數(shù)字就是由給定的素數(shù)因子組成的數(shù)字,給出n,要求返回第n個丑陋數(shù)字。而且素數(shù)因子是有序遞增排列的。我心想,這么簡單!直接一個for循環(huán)一次把素數(shù)因子數(shù)組從低到高乘起來不就可以了嗎?仔細(xì)分析下來發(fā)現(xiàn)并沒有這么簡單。例如,丑陋數(shù)字?jǐn)?shù)組的第三個數(shù)字是4,即1X2X2,而不是1X2X7!說明有的數(shù)字乘兩次了都還比另外的數(shù)字乘一次要小!所以說前面的那種想法是錯誤的。再思考,每次都乘2會不會就是最小?這個不用想,肯定是錯的,因為比如說第四個數(shù)字如果是1X7就比1X2X2X2要小。我們設(shè)丑陋數(shù)字?jǐn)?shù)組為superuglynumbers[n]。1X7就是superuglynumbers[0]X7,而122*2就是superuglynumbers[2]X2,為什么它是后者用的是superuglynumbers[2]而前者是superuglynumbers[0]呢?
這里很顯然就會想到次數(shù)的問題,因為我的數(shù)字2在之前用過兩次,所以它會“認(rèn)為”當(dāng)前最小的數(shù)字就是丑陋數(shù)字?jǐn)?shù)組的前一項superuglynumbers[2]乘以素數(shù)數(shù)組里面最小的數(shù)字2。而不是superuglynumbers[1]X2,因為這個組合它之前用過了,不能再用了,再用的話丑陋數(shù)字就重復(fù)出現(xiàn)了。但是并不一定它就是最小。
你應(yīng)該看出來了,它用了4個數(shù)字相乘,而1X7只用了兩個數(shù)字相乘。畫個圖你就明白了:
從圖中你可以看出每個數(shù)字都是乘在它上一次的“高度”上。
解
我們可以用一個數(shù)組times[]來記錄每個素數(shù)的用到的次數(shù),也就是它的“高度”。每當(dāng)它乘以上一個高度的值是真正地最小值時,就將它的高度+1,其它數(shù)字的高度保持不變。好了,清楚了邏輯,我們就可以上代碼了。
public static int nthSuperUglyNumber(int n,int[] primers){
int[] times=new int[primers.length];
int[] uglynumbers=new int[n];
uglynumbers[0]=1;
for(int i=1;i<n;i++){
int min=Integer.MAX_VALUE;
for(int j=0;j<primers.length;j++){
min=Math.min(min,primers[j]*uglynumbers[times[j]]);
}
uglynumbers[i]=min;
for(int j=0;j<times.length;j++){
if(primers[j]*uglynumbers[times[j]]==min){
times[j]++;
}
}
}
return uglynumbers[n-1];
}
昨天去學(xué)校圖書館,坐下來才發(fā)現(xiàn)沒有帶草稿本,于是就在那里干想,想了很久,還是畫圖好理解一點。