[Swift]LeetCode756. 金字塔轉換矩陣 | Pyramid Transition Matrix

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公衆號:山青詠芝(shanqingyongzhi)
➤博客園地址:山青詠芝(https://www.cnblogs.com/strengthen/
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址: http://www.javashuo.com/article/p-ginieobb-me.html 
➤若是連接不是山青詠芝的博客園地址,則多是爬取做者的文章。
➤原文已修改更新!強烈建議點擊原文地址閱讀!支持做者!支持原創!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★html

We are stacking blocks to form a pyramid. Each block has a color which is a one letter string, like `'Z'`.git

For every block of color `C` we place not in the bottom row, we are placing it on top of a left block of color `A` and right block of color `B`. We are allowed to place the block there only if `(A, B, C)` is an allowed triple.github

We start with a bottom row of bottom, represented as a single string. We also start with a list of allowed triples allowed. Each allowed triple is represented as a string of length 3.數組

Return true if we can build the pyramid all the way to the top, otherwise false.微信

Example 1:app

Input: bottom = "XYZ", allowed = ["XYD", "YZE", "DEA", "FFF"]
Output: true
Explanation:
We can stack the pyramid like this:
    A
   / \
  D   E
 / \ / \
X   Y   Z

This works because ('X', 'Y', 'D'), ('Y', 'Z', 'E'), and ('D', 'E', 'A') are allowed triples. 

Example 2:ide

Input: bottom = "XXYX", allowed = ["XXX", "XXY", "XYX", "XYY", "YXZ"]
Output: false
Explanation:
We can't stack the pyramid to the top.
Note that there could be allowed triples (A, B, C) and (A, B, D) with C != D. 

Note:函數

  1. bottom will be a string with length in range [2, 8].
  2. allowed will have length in range [0, 200].
  3. Letters in all strings will be chosen from the set {'A', 'B', 'C', 'D', 'E', 'F', 'G'}.

如今,咱們用一些方塊來堆砌一個金字塔。 每一個方塊用僅包含一個字母的字符串表示,例如 「Z」。ui

使用三元組表示金字塔的堆砌規則以下:this

(A, B, C) 表示,「C」爲頂層方塊,方塊「A」、「B」分別做爲方塊「C」下一層的的左、右子塊。當且僅當(A, B, C)是被容許的三元組,咱們才能夠將其堆砌上。

初始時,給定金字塔的基層 bottom,用一個字符串表示。一個容許的三元組列表 allowed,每一個三元組用一個長度爲 3 的字符串表示。

若是能夠由基層一直堆到塔尖返回true,不然返回false。

示例 1:

輸入: bottom = "XYZ", allowed = ["XYD", "YZE", "DEA", "FFF"]
輸出: true
解析:
能夠堆砌成這樣的金字塔:
    A
   / \
  D   E
 / \ / \
X   Y   Z

由於符合('X', 'Y', 'D'), ('Y', 'Z', 'E') 和 ('D', 'E', 'A') 三種規則。

示例 2:

輸入: bottom = "XXYX", allowed = ["XXX", "XXY", "XYX", "XYY", "YXZ"]
輸出: false
解析:
沒法一直堆到塔尖。
注意, 容許存在三元組(A, B, C)和 (A, B, D) ,其中 C != D.

注意:

  1. bottom 的長度範圍在 [2, 8]
  2. allowed 的長度範圍在[0, 200]
  3. 方塊的標記字母範圍爲{'A', 'B', 'C', 'D', 'E', 'F', 'G'}

24ms

 1 class Solution {
 2     func pyramidTransition(_ bottom: String, _ allowed: [String]) -> Bool {
 3         var patterDict = [String: [String]]()
 4         for w in allowed {
 5            let key = String(w.prefix(2))
 6             let val = String(w.suffix(1))
 7             if patterDict[key] == nil {
 8                 patterDict[key] = [String]()
 9             }
10             patterDict[key]?.append(val)
11         }
12         
13         func buildNext(_ A: String, _ ans: String, _ i: Int) -> Bool {
14             //print("A = \(A), ans = \(ans), A = \(i)")
15             if A.count == 0 {  //找到可行解
16                 return true
17             }
18             if i + 1 == A.count {  //某一排所有擺放完成
19                 return buildNext(ans, "", 0)
20             }
21             let w = A.subString(from: i, length: 2)
22             if let dic = patterDict[w] {
23                 for x in dic {
24                     if buildNext(A, ans + x, i + 1) {
25                         return true
26                     }
27                 }
28             } else {
29                 return false
30             }
31 
32             return false
33         }
34 
35         return buildNext(bottom, "", 0)
36     }
37 }
38 
39 extension String {
40     func subString(from: Int, length: Int) -> String {
41         let indexStartOfText = self.index(self.startIndex, offsetBy: from)
42         let indexEndOfText = self.index(self.startIndex, offsetBy: from + length)
43         let substring = self[indexStartOfText..<indexEndOfText]
44         return String(substring)
45     }
46 }

40ms

 1 class Solution {
 2     func pyramidTransition(_ bottom: String, _ allowed: [String]) -> Bool {
 3         var map = [String: [Character]]()
 4         for s in allowed {
 5             let key = String(s.prefix(2))
 6             var arr = map[key, default: [Character]()]
 7             arr.append(s.last!)
 8             map[key] = arr
 9         }
10         var curr = ""
11         var pre = bottom
12         return DFS(&pre, &curr, 0, map)
13     }
14 
15     func DFS(_ prev: inout String, _ curr: inout String, _ idx: Int, _ map: [String: [Character]]) -> Bool {
16         if prev.count == 1 {                   // the total pyramid has been constructed
17             return true
18         }
19         if idx + 1 == prev.count {               // the current layer has been constructed
20             var next = ""
21             return DFS(&curr, &next, 0, map);
22         }
23         else {
24             let chars = Array(prev)
25             let key = String(chars[idx..<idx+2])
26             if map[key] == nil {  // no candidate
27                 return false
28             }
29             else {                                  // try each candidate
30                 let chars = map[key]!
31                 for i in 0..<chars.count {
32                     curr.append(chars[i])
33                     if DFS(&prev, &curr, idx+1, map) { return true }
34                     curr.popLast() // backtracking
35                 }
36                 return false
37             }
38         }
39     }
40 }

Runtime: 44 ms
Memory Usage: 20 MB
 1 class Solution {
 2     let arrChar:[Character] = ["A","B","C","D","E","F","G"]
 3     func pyramidTransition(_ bottom: String, _ allowed: [String]) -> Bool {
 4         var n:Int = bottom.count
 5         var dp:[[[Bool]]] = [[[Bool]]](repeating:[[Bool]](repeating:[Bool](repeating:false,count:7),count:n),count:n)
 6         var m:[Character:Set<String>] = [Character:Set<String>]()
 7         for str in allowed
 8         {
 9             m[str[2],default:Set<String>()].insert(str.subString(0, 2))
10         }
11         for i in 0..<n
12         {
13             dp[n - 1][i][bottom[i].ascii - 65] = true
14         }
15         for i in stride(from:n - 2,through:0,by:-1)
16         {
17             for j in 0...i
18             {
19                 for ch in arrChar
20                 {
21                     if m[ch] == nil {continue}
22                     for str in m[ch]!
23                     {
24                         if dp[i + 1][j][str[0].ascii - 65] && dp[i + 1][j + 1][str[1].ascii - 65]
25                         {
26                             dp[i][j][ch.ascii - 65] = true
27                         }
28                     }
29                 }
30             }
31         }
32         for i in 0..<7
33         {
34             if dp[0][0][i] {return true}
35         }
36         return false
37     }
38 }
39 
40 extension String {
41     //subscript函數能夠檢索數組中的值
42     //直接按照索引方式截取指定索引的字符
43     subscript (_ i: Int) -> Character {
44         //讀取字符
45         get {return self[index(startIndex, offsetBy: i)]}
46     }
47     
48     // 截取字符串:指定索引和字符數
49     // - begin: 開始截取處索引
50     // - count: 截取的字符數量
51     func subString(_ begin:Int,_ count:Int) -> String {
52         let start = self.index(self.startIndex, offsetBy: max(0, begin))
53         let end = self.index(self.startIndex, offsetBy:  min(self.count, begin + count))
54         return String(self[start..<end]) 
55     }
56     
57 }
58 
59 //Character擴展 
60 extension Character  
61 {  
62   //Character轉ASCII整數值(定義小寫爲整數值)
63    var ascii: Int {
64        get {
65            return Int(self.unicodeScalars.first?.value ?? 0)
66        }       
67     }    
68 }
相關文章
相關標籤/搜索