[LeetCode] Pyramid Transition Matrix 金字塔转变矩阵
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:
bottom
will be a string with length in range[2, 8]
.allowed
will have length in range[0, 200]
.- Letters in all strings will be chosen from the set
{'A', 'B', 'C', 'D', 'E', 'F', 'G'}
.
这道题让我们累一个金字塔,用字母来代表每块砖的颜色,给了一个allowed数组,里面都是长度为三的字符串,比如“ABC”表示C可以放在A和B的上方,注意AB上面也可以放其他的,比如“ABD”也可以同时出现,不过搭积木的时候只能选择一种。给了我们一个bottom字符串,是金字塔的底层,问我们能不能搭出一个完整的金字塔。那么实际上我们就是从底层开始,一层一层的向上来累加,直到搭出整个金字塔。我们先来看递归的解法,首先由于我们想快速知道两个字母上方可以放的字母,需要建立基座字符串和上方字符集合之间的映射,由于上方字符可以不唯一,所以用个HashSet来放字符。我们的递归函数有三个参数,当前层字符串cur,上层字符串above,还有我们的HashMap。如果cur的大小为2,above的大小为1,那么说明当前已经达到金字塔的顶端了,已经搭出来了,直接返回true。否则看,如果上一层的长度比当前层的长度正好小一个,说明上一层也搭好了,我们现在去搭上上层,于是调用递归函数,将above当作当前层,空字符串为上一层,将调用的递归函数结果直接返回。否则表示我们还需要继续去搭above层,我们先算出above层的长度pos,然后从当前层的pos位置开始取两个字符,就是above层接下来需要搭的字符的基座字符,举个例子如下:
D
/ \ / \
A B C
我们看到现在above层只有一个D,那么pos为1,在cur层1位置开始取两个字符,得到"BC",即是D的下一个位置的字符的基座字符串base。取出了base后,如果HashMap中有映射,则我们遍历其映射的字符集合中的所有字符,对每个字符都调用递归函数,此时above字符串需要加上这个遍历到的字符,因为我们在尝试填充这个位置,如果有返回true的,那么当前递归函数就返回true了,否则最终返回false,参见代码如下:
解法一:
class Solution {
public:
bool pyramidTransition(string bottom, vector<string>& allowed) {
unordered_map<string, unordered_set<char>> m;
for (string str : allowed) {
m[str.substr(, )].insert(str[]);
}
return helper(bottom, "", m);
}
bool helper(string cur, string above, unordered_map<string, unordered_set<char>>& m) {
if (cur.size() == && above.size() == ) return true;
if (above.size() == cur.size() - ) return helper(above, "", m);
int pos = above.size();
string base = cur.substr(pos, );
if (m.count(base)) {
for (char ch : m[base]) {
if (helper(cur, above + string(, ch), m)) {
return true;
}
}
}
return false;
}
};
下面来看一种迭代的写法,这是一种DP的解法,建立一个三维的dp数组,其中dp[i][j][ch]表示在金字塔(i, j)位置上是否可以放字符ch,金字塔的宽和高已经确定了,都是n。每个位置对应着nxn的数组的左半边,如下所示:
F _ _
D E _
A B C
除了底层,每个位置可能可以放多个字符,所以这里dp数组是一个三维数组,第三维的长度为7,因为题目中限定了字母只有A到G共7个,如果dp值为true,表示该位置放该字母,我们根据bottom字符串来初始化dp数组的底层。这里还是需要一个HashMap,不过跟上面的解法略有不同的是,我们建立上方字母跟其能放的基座字符串集合的映射,因为一个字母可能可以放多个位置,所以用个集合来表示。然后我们就开始从倒数第二层开始往顶部更新啦,对于金字塔的每个位置,我们都遍历A到G中所有的字母,如果当前字母在HashMap中有映射,则我们遍历对应的基座字符串集合中的所有字符串,基座字符串共有两个字母,左边的字母对应的金字塔中的位置是(i + 1, j),右边的字母对应的位置是(i + 1, j + 1),我们只要在这两个位置上分别查询对应的字母的dp值是否为true,是的话,说明当前位置有字母可以放,我们将当前位置的字母对应的dp值赋值为true。这样,当我们整个更新完成了之后,我们只要看金字塔顶端位置(0, 0)是否有字母可以放,有的话,说明可以搭出金字塔,返回true,否则返回false,参见代码如下:
解法二:
class Solution {
public:
bool pyramidTransition(string bottom, vector<string>& allowed) {
int n = bottom.size();
vector<vector<vector<bool>>> dp(n, vector<vector<bool>>(n, vector<bool>(, false)));
unordered_map<char, unordered_set<string>> m;
for (string str : allowed) {
m[str[]].insert(str.substr(, ));
}
for (int i = ; i < n; ++i) {
dp[n - ][i][bottom[i] - 'A'] = true;
}
for (int i = n - ; i >= ; --i) {
for (int j = ; j <= i; ++j) {
for (char ch = 'A'; ch <= 'G'; ++ch) {
if (!m.count(ch)) continue;
for (string str : m[ch]) {
if (dp[i + ][j][str[] - 'A'] && dp[i + ][j + ][str[] - 'A']) {
dp[i][j][ch - 'A'] = true;
}
}
}
}
}
for (int i = ; i < ; ++i) {
if (dp[][][i]) return true;
}
return false;
}
};
参考资料:
https://leetcode.com/problems/pyramid-transition-matrix/discuss/113075/DP-O(n2-*-m)
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] Pyramid Transition Matrix 金字塔转变矩阵的更多相关文章
- LC 756. Pyramid Transition Matrix
We are stacking blocks to form a pyramid. Each block has a color which is a one letter string, like ...
- [LeetCode] 59. Spiral Matrix II 螺旋矩阵 II
Given an integer n, generate a square matrix filled with elements from 1 to n^2 in spiral order. For ...
- [Swift]LeetCode756. 金字塔转换矩阵 | Pyramid Transition Matrix
We are stacking blocks to form a pyramid. Each block has a color which is a one letter string, like ...
- 【LeetCode】756. Pyramid Transition Matrix 解题报告(Python & C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 回溯法 日期 题目地址:https://leetco ...
- 【leetcode】756. Pyramid Transition Matrix
题目如下: We are stacking blocks to form a pyramid. Each block has a color which is a one letter string, ...
- LeetCode 73. Set Matrix Zeros(矩阵赋零)
Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in place. click ...
- LeetCode 54. Spiral Matrix(螺旋矩阵)
Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral or ...
- [LeetCode] 885. Spiral Matrix III 螺旋矩阵之三
On a 2 dimensional grid with R rows and C columns, we start at (r0, c0) facing east. Here, the north ...
- leetcode[73] Set Matrix Zeroes 将矩阵置零
给定一个矩阵,把零值所在的行和列都置为零.例如: 1 2 3 1 3 1 1 1 操作之后变为 1 3 0 0 0 1 1 方法1: 赋值另存一个m*n的矩阵,在原矩阵为零的值相应置新的矩阵行和列为零 ...
随机推荐
- lvs(dr)+keepalived
系统:centos6.5mini 环境: 机器名 Ip地址 角色 Vip-web: 192.168.20.50 Vip-mysql: 192.168.20.60 lvs01 192.168.20.10 ...
- Java多线程:CopyOnWrite容器
一.什么是CopyOnWrite容器 CopyOnWrite容器即写时复制的容器.通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然 ...
- iOS移动端直连数据库
一个可以直接连接服务器MySQL的工具包(极不安全,如非特殊需求,不推荐使用) 这种直接连接服务器数据的方式是极为不安全的,但因为我们这个项目特殊情况,只在局域网内使用, 且只有一个pad对一台设备进 ...
- tensorflow安装过程-(windows环境下)---详解(摆平了很多坑!)
一, 前言:本次安装tensorflow是基于Python的,安装Python的过程不做说明(既然决定按,Python肯定要先了解啊):本次教程是windows下Anaconda安装Tensorflo ...
- poj2991 Crane(线段树+集合)白书例题
题目大意:起重机有n节,题目给出要调节的k节,每节调节成x度,求最后底部的起重机的坐标(最顶上的起点为(0,0)). 分析:一开始我看白书,看不懂他那个向量旋转的坐标是怎么来的,翻了很多博客,才发现, ...
- 如何用Word编辑参考文献------这是引用一位大师的
如何用Word编辑参考文献修改文献是一件非常痛苦的事情,虽然现在也有很多软件可以编排参考文献,其实word本身就可以. 采用合适的编辑方法会方便地做到整齐,规范,自动排序和交叉引用.1.以尾注的方式插 ...
- DEVC使用问题集锦
一.DEVC++编译出现"Id return 1 exit status" 这是初学者刚用DEVC经常碰到问题,一般有如下解决方法: 1.首先检查下是否有c的exe程序开着,若开着 ...
- formidable 表单文件和数据提交
只要涉及文件上传,那么form标签要加一个属性: <form action="http://127.0.0.1/dopost" method="post" ...
- android 广播安装指定下载的apk
// 广播出去,由广播接收器来处理下载完成的文件 Intent sendIntent = new Intent("com.test.downloadComplete"); ...
- Flask 扩展 自定义扩展
创建一个为视图访问加日志的扩展Flask-Logging,并从中了解到写Flask扩展的规范. 创建工程 先创建一个工程,目录结构如下: flask-logging/ ├ LICENSE # 授权说明 ...