题目描述:
现在,我们用一些方块来堆砌一个金字塔。 每个方块用仅包含一个字母的字符串表示,例如 “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.
注意:
bottom 的长度范围在 [2, 8]。
allowed 的长度范围在[0, 200]。
方块的标记字母范围为{‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’, ‘G’}。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/pyramid-transition-matrix
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
递归+回溯+DFS
使用map保存
class Solution {
private Map<String, List<Character>> map;
public boolean pyramidTransition(String bottom, List<String> allowed) {
/**
直接暴力搜索的dfs会超时, 要利用一个map保存所有方块可能的顶部字母
**/
map = new HashMap<>();
for(String brick : allowed) {
String base = brick.substring(0, 2);
if(!map.containsKey(base))
map.put(base, new ArrayList<>());
map.get(base).add(brick.charAt(2));
}
return dfs(bottom);
}
private boolean dfs(String bottom) {
// bottom为1说明到达金字塔顶端, 可以搭成金字塔
if(bottom.length() == 1)
return true;
// 如果bottom中有未出现过的方块底层说明不能搭成金字塔
for(int i = 0; i < bottom.length()-1; ++i)
if(!map.containsKey(bottom.substring(i,i+2)))
return false;
// 根据bottom生成所有可能的上层方块
List<String> candidates = new ArrayList<>();
generateUpper(bottom, candidates, new StringBuilder(), 0);
for(String upper : candidates)
if(dfs(upper))
return true;
return false;
}
private void generateUpper(String bottom, List<String> candidates, StringBuilder sb, int st) {
if(st == bottom.length()-1) {
candidates.add(sb.toString());
return;
}
for(Character c : map.get(bottom.substring(st, st+2))) {
sb.append(c);
generateUpper(bottom, candidates, sb, st+1);
sb.deleteCharAt(sb.length()-1);
}
}
}
自己尝试实现一遍
class Solution {
Map<String, List<Character>> map = new HashMap<>();
public boolean pyramidTransition(String bottom, List<String> allowed) {
for (String string : allowed) {
String tem = string.substring(0,2);
if(map.get(tem) == null){
map.put(tem, new ArrayList<Character>());
}
map.get(tem).add(string.charAt(2));
}
return dfs1(bottom);
}
// 获取到所有的可能的底层
public boolean dfs1(String botom){
if(botom.length() == 1){
return true;
}
for (int i = 0; i < botom.length() - 1; ++i)
if (!map.containsKey(botom.substring(i, i + 2)))
return false;
// 获取到所有的上层建筑
List<String> list = new ArrayList<>();
getupper(list, botom, 0, new StringBuilder());
for (String string : list) {
if(dfs1(string)){
return true;
}
}
return false;
}
public void getupper(List<String> list,String botom,int index,StringBuilder sb){
if(index == botom.length() - 1){
list.add(sb.toString());
return ;
}
for (Character temchar : map.get(botom.substring(index,index + 2))) {
sb.append(temchar);
getupper(list, botom, index + 1, sb);
sb.deleteCharAt(sb.length() -1);
}
}
}