leetcode刷题笔记313题 超级丑数
leetcode刷题笔记313题 超级丑数
源地址:313. 超级丑数
问题描述:
编写一段程序来查找第 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] 。
说明:1 是任何给定 primes 的超级丑数。
给定 primes 中的数字以升序排列。
0 < k ≤ 100, 0 < n ≤ 106, 0 < primes[i] < 1000 。
第 n 个超级丑数确保在 32 位有符整数范围内
//思路一 通过维护最小堆,将每次可能的结果压入优先队列,将同样的结果从堆中排除, 直到n个元素出队列即可
import scala.collection.mutable.PriorityQueue
object Solution {
def nthSuperUglyNumber(n: Int, primes: Array[Int]): Int = {
val heap = PriorityQueue.empty[Long](Ordering.by(n => n)).reverse
var count = n
heap.enqueue(1)
count -= 1
while (count > 0) {
val x = heap.dequeue
while (heap.length > 0 && heap.head == x) {heap.dequeue}
for (i <- 0 to primes.length-1) {
heap.enqueue(x * primes(i))
}
count -= 1
}
return heap.dequeue.toInt
}
}
//基于动态规划 构建dp数组存储丑数序列,index序列存储对应的primes中的质数应该与dp中的那个数求乘积
//而后记录每次的最小值放入, 注意去除重复值
object Solution {
def nthSuperUglyNumber(n: Int, primes: Array[Int]): Int = {
val dp = Array.fill(n)(0)
val index = Array.fill(primes.length)(0)
dp(0) = 1
for (i <- 1 to n-1){
var min = Int.MaxValue
for (j <- 0 to index.length-1) {
if (min > primes(j) * dp(index(j))) {min = primes(j) * dp(index(j))}
}
dp(i) = min
for (j <- 0 to index.length-1) {
if (min == primes(j) * dp(index(j))) {index(j) += 1}
}
}
return dp(n-1)
}
}
//注意go中堆的使用方法
import "container/heap"
type UglyNums []int
func (u *UglyNums) Push(x interface{}) {
*u = append(*u, x.(int))
}
func (u *UglyNums) Pop() interface{} {
n := len(*u)
x := (*u)[n-1]
(*u) = (*u)[0:n-1]
return x
}
func (u UglyNums) Len() int {
return len(u)
}
func (u UglyNums) Less(i, j int) bool {
return u[i] < u[j]
}
func (u UglyNums) Swap(i, j int) {
u[i], u[j] = u[j], u[i]
}
func nthSuperUglyNumber(n int, primes []int) int {
if n == 0 || n == 1 {return n}
curHeap := new(UglyNums)
heap.Push(curHeap, 1)
n--
for (n > 0) {
x := heap.Pop(curHeap).(int)
for (curHeap.Len() > 0 && (*curHeap)[0] == x) {heap.Pop(curHeap)}
for i := 0; i < len(primes); i++ {
heap.Push(curHeap, x*primes[i])
}
n --
}
return heap.Pop(curHeap).(int)
}
//
func nthSuperUglyNumber(n int, primes []int) int {
length := len(primes)
dp := make([]int, n)
index := make([]int, length)
dp[0] = 1
for i := 1; i < n; i++ {
min := math.MaxInt32
for j := 0; j < length; j++ {
if min > primes[j] * dp[index[j]] {min = primes[j] * dp[index[j]]}
}
dp[i] = min
for j := 0; j < length; j++ {
if min == primes[j] * dp[index[j]] {index[j] += 1}
}
}
return dp[n-1]
}