活用動態規劃DP 特殊的騎士撥號器 Knight Dialer_Leetcode #935

更新於 發佈於 閱讀時間約 5 分鐘

題目敘述

題目會給定一組數字鍵盤,要求我們每次撥號的時候都走象棋的"馬"步,也就是日字型的走法,請問給定長度的n的數字撥號方式有幾種?

最後回傳答案之前,記得對109 + 7做除法取餘數。

詳細的題目可在這裡看到

數字鍵盤的配置如下圖

在側邊欄中搜尋

在側邊欄中搜尋

象棋的"馬"步 日字型走法 示意圖

在側邊欄中搜尋

在側邊欄中搜尋


測試範例

Example 1:

Input: n = 1
Output: 10
Explanation: We need to dial a number of length 1, so placing the knight over any numeric cell of the 10 cells is sufficient.

Example 2:

Input: n = 2
Output: 20
Explanation: All the valid number we can dial are [04, 06, 16, 18, 27, 29, 34, 38, 40, 43, 49, 60, 61, 67, 72, 76, 81, 83, 92, 94]

Example 3:

Input: n = 3131
Output: 136006598
Explanation: Please take care of the mod.

約束條件

Constraints:

  • 1 <= n <= 5000

演算法

其實和前面介紹過 計算有幾個母音直線排列 的那題很像,數字鍵盤定義域和值域都是固定的,可以先找出狀態轉移的State transfer diagram。再從狀態機的State transfer diagram實作出bottom-up的DP解法。


從數字鍵盤的位置和撥號規則(走馬步)找出規律

現在狀態,前一個狀態:

現在的0可以由前一步的4, 6走過來

現在的1可以由前一步的6, 8走過來

現在的2可以由前一步的7, 9走過來

現在的3可以由前一步的4, 8走過來

現在的4可以由前一步的0, 3, 9走過來

現在的5 無法由其他數字走過來 (實作上的細節,請留意)

現在的6可以由前一步的0, 1, 7走過來

現在的7可以由前一步的2, 6走過來

現在的8可以由前一步的1, 3走過來

現在的9可以由前一步的2, 4走過來


有了這些狀態轉移關係式後,就可以用迴圈,每次迭代更新數字鍵盤撥號的方法總數。


程式碼

class Solution:
 def knightDialer(self, N):
  
  '''
  State Transfer function
  Cur state comes from previous state
  0   <-> 4, 6
  1   <-> 6, 8
  2   <-> 7, 9
  3   <-> 4, 8
  4   <-> 0, 3, 9
  5   <-> NULL (i.e. No solution when length >= 2 )
  6   <-> 0, 1, 7
  7   <-> 2, 6
  8   <-> 1, 3
  9   <-> 2, 4
  '''

  CONSTANT = 10**9+7
  method_count = [1 for _ in range(10)]

  for step in range(N-1):
   prev = method_count.copy()
   method_count[0] = prev[4] + prev[6]
   method_count[1] = prev[6] + prev[8]
   method_count[2] = prev[7] + prev[9]
   method_count[3] = prev[4] + prev[8]
   method_count[4] = prev[0] + prev[3] + prev[9]
   method_count[5] = 0 # NULL
   method_count[6] = prev[0] + prev[1] + prev[7]
   method_count[7] = prev[2] + prev[6]
   method_count[8] = prev[1] + prev[3]
   method_count[9] = prev[2] + prev[4]

  return sum(method_count) % CONSTANT

複雜度分析

時間複雜度:

O( n ) bottom-up 從 撥號長度為1 開始遞迴更新到 撥號長度為n。

空間複雜度:

O( 1 ) 使用到的是固定大小,長度為10的暫存陣列 prev。


關鍵知識點

關鍵在於從題目給的數字鍵盤的位置 和 走馬步撥號的規則推導每個長度的撥號遞迴狀態轉移關係式

這一題和前面介紹過 計算有幾個母音直線排列 的那題很像,強烈建議一起複習有限狀態及FSM結合DP動態規劃的解題觀念。


Reference:

[1] Python O(n) by Finite State Machine [w/ Visualization] - Knight Dialer - LeetCode

留言
avatar-img
留言分享你的想法!
avatar-img
小松鼠的演算法樂園
96會員
427內容數
由有業界實戰經驗的演算法工程師, 手把手教你建立解題的框架, 一步步寫出高效、清晰易懂的解題答案。 著重在讓讀者啟發思考、理解演算法,熟悉常見的演算法模板。 深入淺出地介紹題目背後所使用的演算法意義,融會貫通演算法與資料結構的應用。 在幾個經典的題目融入一道題目的多種解法,或者同一招解不同的題目,擴展廣度,並加深印象。
2024/06/14
題目敘述 Triangle 題目會給我們一個三角形的二維陣列triangle ,每個元素分別代表每個格子的成本,請問我們從最頂端到底部的下墜路徑的最小成本總和是多少? 每次下墜到下一排的時候,可以有兩種選擇: 1.往左下方的格子點移動。 2.往右下方的格子點移動。 測試範例 Examp
Thumbnail
2024/06/14
題目敘述 Triangle 題目會給我們一個三角形的二維陣列triangle ,每個元素分別代表每個格子的成本,請問我們從最頂端到底部的下墜路徑的最小成本總和是多少? 每次下墜到下一排的時候,可以有兩種選擇: 1.往左下方的格子點移動。 2.往右下方的格子點移動。 測試範例 Examp
Thumbnail
2024/06/08
Minimum Path Sum 給定一個矩陣,每個格子點代表經過的對應成本。 每回合可以往右移動一格或往下移動一格。 請問從起點左上角 走到 終點右下角的最小路徑成本總和是多少?
Thumbnail
2024/06/08
Minimum Path Sum 給定一個矩陣,每個格子點代表經過的對應成本。 每回合可以往右移動一格或往下移動一格。 請問從起點左上角 走到 終點右下角的最小路徑成本總和是多少?
Thumbnail
2024/06/06
DP特訓班的分類目錄 與 推薦的學習、練習順序
Thumbnail
2024/06/06
DP特訓班的分類目錄 與 推薦的學習、練習順序
Thumbnail
看更多
你可能也想看
Thumbnail
題目敘述: 給定一個二維陣列的高與寬,並且給定起點位置座標。 請從起點位置開始順時針拜訪陣列元素,並且把沿路走過的座標記錄下來。 以陣列的形式返回答案。
Thumbnail
題目敘述: 給定一個二維陣列的高與寬,並且給定起點位置座標。 請從起點位置開始順時針拜訪陣列元素,並且把沿路走過的座標記錄下來。 以陣列的形式返回答案。
Thumbnail
題目敘述: 給定一個傳統手機鍵盤,如圖所示 接著給定一個字串word。 現在讓你重新安排每個字母的所在位置,每個字母可以重新安排到2~9這幾個鍵盤上的位置,每個字母限定只能選擇一個數字鍵去對應。 請問重新安排之後,最少要幾次按鍵才能輸出字串word?
Thumbnail
題目敘述: 給定一個傳統手機鍵盤,如圖所示 接著給定一個字串word。 現在讓你重新安排每個字母的所在位置,每個字母可以重新安排到2~9這幾個鍵盤上的位置,每個字母限定只能選擇一個數字鍵去對應。 請問重新安排之後,最少要幾次按鍵才能輸出字串word?
Thumbnail
題目敘述 題目會給我們一個傳統手機的數字鍵盤 和一個數字鍵的輸入字串digits,要求我們列舉出所有輸入字串digits可能對應到的英文字母的排列。 例如輸入digits="23" 那對應到的英文字母排列就是"ad", "ae", "af", "bd", "be", "bf", "cd", "
Thumbnail
題目敘述 題目會給我們一個傳統手機的數字鍵盤 和一個數字鍵的輸入字串digits,要求我們列舉出所有輸入字串digits可能對應到的英文字母的排列。 例如輸入digits="23" 那對應到的英文字母排列就是"ad", "ae", "af", "bd", "be", "bf", "cd", "
Thumbnail
題目敘述 題目會給定一組數字鍵盤,要求我們每次撥號的時候都走象棋的"馬"步,也就是日字型的走法,請問給定長度的n的數字撥號方式有幾種? 最後回傳答案之前,記得對109 + 7做除法取餘數。 詳細的題目可在這裡看到 數字鍵盤的配置如下圖 象棋的"馬"步 日字型走法 示意圖
Thumbnail
題目敘述 題目會給定一組數字鍵盤,要求我們每次撥號的時候都走象棋的"馬"步,也就是日字型的走法,請問給定長度的n的數字撥號方式有幾種? 最後回傳答案之前,記得對109 + 7做除法取餘數。 詳細的題目可在這裡看到 數字鍵盤的配置如下圖 象棋的"馬"步 日字型走法 示意圖
Thumbnail
題目敘述 題目會給我們一個不規則排列的二維陣列,要求我們列出從起點出發,走次對角線,由左下到右上逐層拜訪的路徑。
Thumbnail
題目敘述 題目會給我們一個不規則排列的二維陣列,要求我們列出從起點出發,走次對角線,由左下到右上逐層拜訪的路徑。
Thumbnail
題目敘述 題目會給我們一個陣列,要求我們返回 兩數之和=target所在的陣列索引值。 題目還額外保證,一定剛好有一組解。 測試範例 Example 1: Input: nums = [2,7,11,15], target = 9 Output: [0,1]
Thumbnail
題目敘述 題目會給我們一個陣列,要求我們返回 兩數之和=target所在的陣列索引值。 題目還額外保證,一定剛好有一組解。 測試範例 Example 1: Input: nums = [2,7,11,15], target = 9 Output: [0,1]
Thumbnail
題目給定一個規律變化的二進位字串,問我們第N排,第K個bit是多少? 變化的規律: 上一排的0到下一排展開成01,上一排的1到下一排展開成10 第一排初始化是0 第二排是01 第三排是0110 第四排是01101001 ...其餘依此類推 詳細的題目可在這裡看到
Thumbnail
題目給定一個規律變化的二進位字串,問我們第N排,第K個bit是多少? 變化的規律: 上一排的0到下一排展開成01,上一排的1到下一排展開成10 第一排初始化是0 第二排是01 第三排是0110 第四排是01101001 ...其餘依此類推 詳細的題目可在這裡看到
Thumbnail
題目會給定我們一組十進位表示法的阿拉伯數字,要求我們把它轉換為對應的羅馬數字。
Thumbnail
題目會給定我們一組十進位表示法的阿拉伯數字,要求我們把它轉換為對應的羅馬數字。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News