为有牺牲多壮志,敢教日月换新天。

[Swift]LeetCode756. 金字塔转换矩阵 | Pyramid Transition Matrix

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:山青咏芝(shanqingyongzhi)
➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址: https://www.cnblogs.com/strengthen/p/10532649.html 
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

热烈欢迎,请直接点击!!!

进入博主App Store主页,下载使用各个作品!!!

注:博主将坚持每月上线一个新app!!!

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

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.

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:

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:

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”。

使用三元组表示金字塔的堆砌规则如下:

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

 

 

posted @ 2019-03-14 18:42  为敢技术  阅读(427)  评论(0编辑  收藏  举报