|
59 | 59 |
|
60 | 60 | <!-- 这里可写通用的实现逻辑 -->
|
61 | 61 |
|
| 62 | +**方法一:记忆化搜索** |
| 63 | + |
| 64 | +定义哈希表 $d$ 存放允许的三角形图案,其中键为两个字符,值为对应的字符列表,表示两个字符可以组成一个三角形图案,三角形图案的顶部为值列表的每一项。 |
| 65 | + |
| 66 | +从最底层开始,对于每一层的每两个相邻的字符,如果它们可以组成一个三角形图案,那么就将三角形图案的顶部字符加入到下一层的对应位置的字符列表中,然后对下一层进行递归处理。 |
| 67 | + |
| 68 | +时间复杂度 $O(C^N)$。其中 $C$ 是字符集的大小,而 $N$ 是 `bottom` 字符串的长度。 |
| 69 | + |
62 | 70 | <!-- tabs:start -->
|
63 | 71 |
|
64 | 72 | ### **Python3**
|
65 | 73 |
|
66 | 74 | <!-- 这里可写当前语言的特殊实现逻辑 -->
|
67 | 75 |
|
68 | 76 | ```python
|
69 |
| - |
| 77 | +class Solution: |
| 78 | + def pyramidTransition(self, bottom: str, allowed: List[str]) -> bool: |
| 79 | + @cache |
| 80 | + def dfs(s): |
| 81 | + if len(s) == 1: |
| 82 | + return True |
| 83 | + t = [] |
| 84 | + for a, b in pairwise(s): |
| 85 | + cs = d[a, b] |
| 86 | + if not cs: |
| 87 | + return False |
| 88 | + t.append(cs) |
| 89 | + return any(dfs(''.join(nxt)) for nxt in product(*t)) |
| 90 | + |
| 91 | + d = defaultdict(list) |
| 92 | + for a, b, c in allowed: |
| 93 | + d[a, b].append(c) |
| 94 | + return dfs(bottom) |
70 | 95 | ```
|
71 | 96 |
|
72 | 97 | ### **Java**
|
73 | 98 |
|
74 | 99 | <!-- 这里可写当前语言的特殊实现逻辑 -->
|
75 | 100 |
|
76 | 101 | ```java
|
| 102 | +class Solution { |
| 103 | + private int[][] f = new int[7][7]; |
| 104 | + private Map<String, Boolean> dp = new HashMap<>(); |
| 105 | + |
| 106 | + public boolean pyramidTransition(String bottom, List<String> allowed) { |
| 107 | + for (String s : allowed) { |
| 108 | + int a = s.charAt(0) - 'A', b = s.charAt(1) - 'A'; |
| 109 | + f[a][b] |= 1 << (s.charAt(2) - 'A'); |
| 110 | + } |
| 111 | + return dfs(bottom, new StringBuilder()); |
| 112 | + } |
| 113 | + |
| 114 | + boolean dfs(String s, StringBuilder t) { |
| 115 | + if (s.length() == 1) { |
| 116 | + return true; |
| 117 | + } |
| 118 | + if (t.length() + 1 == s.length()) { |
| 119 | + return dfs(t.toString(), new StringBuilder()); |
| 120 | + } |
| 121 | + String k = s + "." + t.toString(); |
| 122 | + if (dp.containsKey(k)) { |
| 123 | + return dp.get(k); |
| 124 | + } |
| 125 | + int a = s.charAt(t.length()) - 'A', b = s.charAt(t.length() + 1) - 'A'; |
| 126 | + int cs = f[a][b]; |
| 127 | + for (int i = 0; i < 7; ++i) { |
| 128 | + if (((cs >> i) & 1) == 1) { |
| 129 | + t.append((char) ('A' + i)); |
| 130 | + if (dfs(s, t)) { |
| 131 | + dp.put(k, true); |
| 132 | + return true; |
| 133 | + } |
| 134 | + t.deleteCharAt(t.length() - 1); |
| 135 | + } |
| 136 | + } |
| 137 | + dp.put(k, false); |
| 138 | + return false; |
| 139 | + } |
| 140 | +} |
| 141 | +``` |
| 142 | + |
| 143 | +### **C++** |
| 144 | + |
| 145 | +```cpp |
| 146 | +class Solution { |
| 147 | +public: |
| 148 | + int f[7][7]; |
| 149 | + unordered_map<string, bool> dp; |
| 150 | + |
| 151 | + bool pyramidTransition(string bottom, vector<string>& allowed) { |
| 152 | + memset(f, 0, sizeof f); |
| 153 | + for (auto& s : allowed) { |
| 154 | + int a = s[0] - 'A', b = s[1] - 'A'; |
| 155 | + f[a][b] |= 1 << (s[2] - 'A'); |
| 156 | + } |
| 157 | + return dfs(bottom, ""); |
| 158 | + } |
| 159 | + |
| 160 | + bool dfs(string& s, string t) { |
| 161 | + if (s.size() == 1) { |
| 162 | + return true; |
| 163 | + } |
| 164 | + if (t.size() + 1 == s.size()) { |
| 165 | + return dfs(t, ""); |
| 166 | + } |
| 167 | + string k = s + "." + t; |
| 168 | + if (dp.count(k)) { |
| 169 | + return dp[k]; |
| 170 | + } |
| 171 | + int a = s[t.size()] - 'A', b = s[t.size() + 1] - 'A'; |
| 172 | + int cs = f[a][b]; |
| 173 | + for (int i = 0; i < 7; ++i) { |
| 174 | + if ((cs >> i) & 1) { |
| 175 | + if (dfs(s, t + (char) (i + 'A'))) { |
| 176 | + dp[k] = true; |
| 177 | + return true; |
| 178 | + } |
| 179 | + } |
| 180 | + } |
| 181 | + dp[k] = false; |
| 182 | + return false; |
| 183 | + } |
| 184 | +}; |
| 185 | +``` |
77 | 186 |
|
| 187 | +### **Go** |
| 188 | +
|
| 189 | +```go |
| 190 | +func pyramidTransition(bottom string, allowed []string) bool { |
| 191 | + f := make([][]int, 7) |
| 192 | + for i := range f { |
| 193 | + f[i] = make([]int, 7) |
| 194 | + } |
| 195 | + for _, s := range allowed { |
| 196 | + a, b := s[0]-'A', s[1]-'A' |
| 197 | + f[a][b] |= 1 << (s[2] - 'A') |
| 198 | + } |
| 199 | + dp := map[string]bool{} |
| 200 | + var dfs func(s string, t []byte) bool |
| 201 | + dfs = func(s string, t []byte) bool { |
| 202 | + if len(s) == 1 { |
| 203 | + return true |
| 204 | + } |
| 205 | + if len(t)+1 == len(s) { |
| 206 | + return dfs(string(t), []byte{}) |
| 207 | + } |
| 208 | + k := s + "." + string(t) |
| 209 | + if v, ok := dp[k]; ok { |
| 210 | + return v |
| 211 | + } |
| 212 | + a, b := s[len(t)]-'A', s[len(t)+1]-'A' |
| 213 | + cs := f[a][b] |
| 214 | + for i := 0; i < 7; i++ { |
| 215 | + if ((cs >> i) & 1) == 1 { |
| 216 | + t = append(t, byte('A'+i)) |
| 217 | + if dfs(s, t) { |
| 218 | + dp[k] = true |
| 219 | + return true |
| 220 | + } |
| 221 | + t = t[:len(t)-1] |
| 222 | + } |
| 223 | + } |
| 224 | + dp[k] = false |
| 225 | + return false |
| 226 | + } |
| 227 | + return dfs(bottom, []byte{}) |
| 228 | +} |
78 | 229 | ```
|
79 | 230 |
|
80 | 231 | ### **...**
|
|
0 commit comments