154 - 264 丑数2
题目
编写一个程序,找出第 n 个丑数。
丑数就是只包含质因数 2, 3, 5 的正整数。
示例:
输入: n = 10 输出: 12 解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 个丑数。
说明:
1 是丑数。
n 不超过1690。
解答
能想到的方法,就是不断除2,3,5,如果除光了就是丑数了。
https://leetcode-cn.com/problems/ugly-number-ii/solution/dui-he-dong-tai-gui-hua-by-powcai/
小顶堆
维护一个小顶堆,根就是最小值。因此每次把最小值拿出来,乘以2,3,5,就是丑数的可能性。
循环n遍拿的最小值,就是答案了
class Solution:
def nthUglyNumber(self, n: int) -> int:
import heapq
heap = [1]
heapq.heapify(heap)
res = 0
for _ in range(n):
res = heapq.heappop(heap)
while heap and res == heap[0]:
res = heapq.heappop(heap)
a, b, c = res*2, res*3, res*5
for t in [a, b, c]:
heapq.heappush(heap, t)
return res
Runtime: 244 ms, faster than 28.36% of Python3 online submissions for Ugly Number II.
Memory Usage: 12.8 MB, less than 100.00% of Python3 online submissions for Ugly Number II.
动态规划
dp[i] = min(2 * dp[i2], 3 * dp[i3], 5 * dp[i5])
丑数是,2、3、5的倍数。即丑数=n个2*2+m个3*3+k个5*5
。比如dp[1]= 2 = 1*2+0*3+0*5
我们要维护一个数组,里面是丑数从小到大排列,第n个值就是答案。
也就是说,在数组里的每个数,在未来数组里面都会被2、3、5乘一遍
于是我们就维护三个指针,分别指下一个还没被2乘、3乘、5乘的数。然后取最小值记录在dp里面
class Solution:
def nthUglyNumber(self, n: int) -> int:
dp = [0]*n
dp[0] = 1
i2 = i3 = i5 = 0
for i in range(1, n):
dp[i] = min(2*dp[i2], 3*dp[i3], 5*dp[i5])
if dp[i] == dp[i2]*2:
i2 += 1
if dp[i] == dp[i3]*3:
i3 += 1
if dp[i] == dp[i5]*5:
i5 += 1
return dp[-1]
Runtime: 156 ms, faster than 73.55% of Python3 online submissions for Ugly Number II.
Memory Usage: 12.8 MB, less than 100.00% of Python3 online submissions for Ugly Number II.
var nthUglyNumber = function(n) {
const dp = new Array(n)
dp[0] = 1
let i2 = 0,
i3 = 0,
i5 = 0
for (let i = 1; i < n; i++) {
dp[i] = Math.min(2 * dp[i2], 3 * dp[i3], 5 * dp[i5])
if (dp[i] === 2 * dp[i2]) {
i2++
}
if (dp[i] === 3 * dp[i3]) {
i3++
}
if (dp[i] === 5 * dp[i5]) {
i5++
}
}
return dp[n - 1]
};
Runtime: 68 ms, faster than 75.68% of JavaScript online submissions for Ugly Number II.
Memory Usage: 36.4 MB, less than 100.00% of JavaScript online submissions for Ugly Number II.
func min(a, b, c int) int {
var m int
if a < b {
m = a
} else {
m = b
}
if c < m {
return c
} else {
return m
}
}
func nthUglyNumber(n int) int {
dp := make([]int, n)
dp[0] = 1
var i2, i3, i5 int
for i := 1; i < n; i++ {
dp[i] = min(dp[i2]*2, dp[i3]*3, dp[i5]*5)
if dp[i] == dp[i2]*2 {
i2++
}
if dp[i] == dp[i3]*3 {
i3++
}
if dp[i] == dp[i5]*5 {
i5++
}
}
return dp[n-1]
}
Runtime: 0 ms, faster than 100.00% of Go online submissions for Ugly Number II.
Memory Usage: 4.1 MB, less than 42.86% of Go online submissions for Ugly Number II.
Last updated
Was this helpful?