思路:把只包含因子 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九個醜數,我們發現這種方法得到的醜數是重複且無序的,不符合要求。
那麼我們可以維護三個佇列:
(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放入三個佇列;(詳細可以參考這裡哦┏ (゜ω゜)=☞)
我們可以看出,每個佇列中的醜數說有序的,且隊頭是最小的,那麼我們每次從三個隊頭中取乙個最小的不就行了嗎。那我們是否真的需要構建這三個佇列呢,我覺得並不需要,我們只需要每次儲存並更新三個隊頭即可,每次使用完哪個隊頭就更新哪個隊頭(乘相應的2,3或5),完整**如下:
public
intgetuglynumber_solution
(int n)
return dp[n -1]
;}
接下來看我第二次做的錯誤答案:
public
intnthuglynumber
(int n)
return dp[n-1]
;}
錯誤原因已經標記出來了,題目要求每個數的因子只包含2,3,5而不是含有2,3,5!!並且也不可以用用else if,會導致出現重複元素!
所以應該用dp陣列來儲存上次遺留下的最小值,在它的基礎上進行操作:
public
intnthuglynumber
(int n)
return dp[n-1]
;}
注意指標都初始化為0噢~
思路:編寫一段程式來查詢第 n 個超級醜數。超級醜數是指其所有質因數都是長度為 k 的質數列表 primes 中的正整數。
輸入: n =
12, primes =[2
,7,13
,19]輸出:
32 解釋: 給定長度為 4 的質數列表 primes =[2
,7,13
,19],前 12 個超級醜數序列為:[1,
2,4,
7,8,
13,14,
16,19,
26,28,
32] 。
public
intnthsuperuglynumber
(int n,
int[
] primes)
for(
int j=
0;jdp[i]
= min;
}return dp[n -1]
;}
還可以用小頂堆,不過一定要記得去重!!並且注意要使用long不然中間有的比較大的數會溢位。這種方法效率很低。
public
intnthsuperuglynumber
(int n,
int[
] primes)
res=queue.
poll()
;while
(!queue.
isempty()
&&res==queue.
peek()
) queue.
poll()
;//去重
}return
(int
)res;
}
思路:
比較基礎的方式是使用堆:
public list
>
ksmallestpairs
(int
nums1,
int[
] nums2,
int k)
// });
priorityqueue<
int[
]> maxheap =
newpriorityqueue
<
int[
]>
((o1,o2)
->);
for(
int i=
0;imaxheap.
add(tmp);if
(maxheap.
size()
> k)}}
list
> res =
newarraylist
<
>()
;while
(!maxheap.
isempty()
)return res;
}public
intgetsum
(int
o)
另一種方法和之前幾個題目思想很像,用乙個陣列來記錄num1中每個元素在nums2中走了多遠就可以,每次迴圈都是nums1和nums2加起來最小的nums1往前走一步:
public list
>
ksmallestpairs
(int
nums1,
int[
] nums2,
int k)
list
> res =
newarraylist
<
>()
;if(nums1.length ==
0|| nums2.length ==0)
return res;
int[
] steps =
newint
[nums1.length]
;for
(int i=
0;ilist
list =
newarraylist
<
>()
; list.
add(nums1[minstepindex]);
list.
add(nums2[steps[minstepindex]])
; res.
add(list)
; steps[minstepindex]++;
}return res;
}
力扣解題思路 32 最長有效括號 糾錯記錄
思路 給定乙個只包含 和 的字串,找出最長的包含有效括號的子串的長度。輸入 輸出 2 解釋 最長有效括號子串為 輸入 輸出 4 解釋 最長有效括號子串為 這一題和22.括號生成類似,首先想到的是用棧來解決,先看一下我的錯誤 int count 0 stack stack newstack for i...
力扣解題思路 14 最長公共字首 糾錯記錄
思路 編寫乙個函式來查詢字串陣列中的最長公共字首。如果不存在公共字首,返回空字串 輸入 flower flow flight 輸出 fl 我首先想到的就是先取第乙個字串作為基準,然後再建立乙個整數陣列 長度和第乙個字串一樣長 然後用其他幾個字串和他相比較 相同的字元則在對應位置加1 後來一想發現不僅...
力扣解題思路 402 移掉K位數字 糾錯記錄
思路 這一題寫出來還算順利,不過主要得益於我看了題目的標籤,不然我可能不會採用棧 o 我首先觀察題目所給的例子,然後在草稿紙上模擬一下整個過程,具體是這樣的 遇到比棧頂更大的元素就直接出棧,若比棧頂小則說明此時棧頂是棧中最大的元素,在k大於0的情況下棧頂出棧,知道當前元素滿足入棧條件 stack s...