Hard草稿★★★★★O(n) 時間 · O(1) 空間
Dynamic Programming
Patterns🔲 網格・雙序列 DP
尚未複習過

解法已隱藏 — 先讀題目敘述、自己想想看,再點上方按鈕揭曉。

1220Count Vowels Permutation2-D DPHard2-D DP

給定一個整數 n,計算長度為 n 的字串中,由母音字母 (a, e, i, o, u) 組成且符合以下規則的字串數量(結果對 10^9+7 取餘):

  • a 後面只能接 e
  • e 後面只能接 ai
  • i 後面不能接 i
  • o 後面只能接 iu
  • u 後面只能接 a

Example:

Input: n = 2 Output: 10

Intuition

TIP

狀態轉移 DP:根據每個母音的後繼規則,逐步累加長度為 n 的合法排列數。

Approaches

1. 2D DP — O(n) / O(n)
  • Idea: dp[i][v] 表示長度為 i、以母音 v 結尾的字串數。根據轉移規則從 dp[i-1] 推導。
  • Time: O(n)
  • Space: O(n)
class Solution {
    fun countVowelPermutation(n: Int): Int {
        val MOD = 1_000_000_007L
        val dp = Array(n) { LongArray(5) }
        // 0=a, 1=e, 2=i, 3=o, 4=u
        for (j in 0..4) dp[0][j] = 1

        for (i in 1 until n) {
            dp[i][0] = (dp[i - 1][1] + dp[i - 1][2] + dp[i - 1][4]) % MOD
            dp[i][1] = (dp[i - 1][0] + dp[i - 1][2]) % MOD
            dp[i][2] = (dp[i - 1][1] + dp[i - 1][3]) % MOD
            dp[i][3] = dp[i - 1][2] % MOD
            dp[i][4] = (dp[i - 1][2] + dp[i - 1][3]) % MOD
        }
        return (dp[n - 1].sum() % MOD).toInt()
    }
}
⭐ 2. Space-Optimized DP — O(n) / O(1)
  • Idea: 只需要五個變數記錄上一輪各母音的數量。
  • Time: O(n)
  • Space: O(1)
class Solution {
    fun countVowelPermutation(n: Int): Int {
        val MOD = 1_000_000_007L
        var a = 1L; var e = 1L; var i = 1L; var o = 1L; var u = 1L

        repeat(n - 1) {
            val na = (e + i + u) % MOD
            val ne = (a + i) % MOD
            val ni = (e + o) % MOD
            val no = i % MOD
            val nu = (i + o) % MOD
            a = na; e = ne; i = ni; o = no; u = nu
        }
        return ((a + e + i + o + u) % MOD).toInt()
    }
}

🔑 Takeaways