1. 程式人生 > 實用技巧 >leetcode刷題筆記313題 超級醜數

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]
}