[LeetCode] Longest Line of Consecutive One in Matrix 矩阵中最长的连续1
Given a 01 matrix M, find the longest line of consecutive one in the matrix. The line could be horizontal, vertical, diagonal or anti-diagonal.
Example:
Input:
[[0,1,1,0],
[0,1,1,0],
[0,0,0,1]]
Output: 3
Hint: The number of elements in the given matrix will not exceed 10,000.
这道题给了我们一个二维矩阵,让我们求矩阵中最长的连续1,连续方向任意,可以是水平,竖直,对角线或者逆对角线均可。那么最直接最暴力的方法就是四个方向分别来统计最长的连续1,其中水平方向和竖直方向都比较容易,就是逐行逐列的扫描,使用一个计数器,如果当前位置是1,则计数器自增1,并且更新结果res,否则计数器清零。对于对角线和逆对角线需要进行些坐标转换,对于一个mxn的矩阵,对角线和逆对角线的排数都是m+n-1个,难点在于我们要确定每一排上的数字的坐标,如果i是从0到m+n-1之间遍历,j是在i到0之间遍历,那么对角线的数字的坐标就为(i-j, j),逆对角线的坐标就为(m-1-i+j, j),这是博主千辛万苦试出来的T.T,如果能直接记住,效果肯定棒!那么有了坐标转换,求对角线和逆对角线的连续1也就不是啥难事了,参见代码如下:
解法一:
class Solution {
public:
int longestLine(vector<vector<int>>& M) {
if (M.empty() || M[].empty()) return ;
int res = , m = M.size(), n = M[].size();
for (int i = ; i < m; ++i) { // Check horizontal
int cnt = ;
for (int j = ; j < n; ++j) {
if (M[i][j] == ) res = max(res, ++cnt);
else cnt = ;
}
}
for (int j = ; j < n; ++j) {
int cnt = ;
for (int i = ; i < m; ++i) { // Check vertical
if (M[i][j] == ) res = max(res, ++cnt);
else cnt = ;
}
}
for (int i = ; i < m + n - ; ++i) {
int cnt1 = , cnt2 = ;
for (int j = i; j >= ; --j) {
if (i - j < m && j < n) { // Check diagonal
if (M[i - j][j] == ) res = max(res, ++cnt1);
else cnt1 = ;
}
int t = m - - i + j;
if (t >= && t < m && j < n ) { // Check anti-diagonal
if(M[t][j] == ) res = max(res, ++cnt2);
else cnt2 = ;
}
}
}
return res;
}
};
如果上面的解法的坐标转换不好想的话,我们也可以考虑用DP解法来做,我们建立一个三维dp数组,其中dp[i][j][k]表示从开头遍历到数字nums[i][j]为止,第k种情况的连续1的个数,k的值为0,1,2,3,分别对应水平,竖直,对角线和逆对角线这四种情况。之后就是更新dp数组的过程了,如果如果数字为0的情况直接跳过,然后水平方向就加上前一个的dp值,竖直方向加上上面一个数字的dp值,对角线方向就加上右上方数字的dp值,逆对角线就加上左上方数字的dp值,然后每个值都用来更新结果res,参见代码如下:
解法二:
class Solution {
public:
int longestLine(vector<vector<int>>& M) {
if (M.empty() || M[].empty()) return ;
int m = M.size(), n = M[].size(), res = ;
vector<vector<vector<int>>> dp(m, vector<vector<int>>(n, vector<int>()));
for (int i = ; i < m; ++i) {
for (int j = ; j < n; ++j) {
if (M[i][j] == ) continue;
for (int k = ; k < ; ++k) dp[i][j][k] = ;
if (j > ) dp[i][j][] += dp[i][j - ][]; // horizonal
if (i > ) dp[i][j][] += dp[i - ][j][]; // vertical
if (i > && j < n - ) dp[i][j][] += dp[i - ][j + ][]; // diagonal
if (i > && j > ) dp[i][j][] += dp[i - ][j - ][]; // anti-diagonal
res = max(res, max(dp[i][j][], dp[i][j][]));
res = max(res, max(dp[i][j][], dp[i][j][]));
}
}
return res;
}
};
下面我们来优化空间复杂度,用一种类似于DFS的思路来解决问题,我们在遍历到为1的点时,对其水平方向,竖直方向,对角线方向和逆对角线方向分别不停遍历,直到越界或者遇到为0的数字,同时用计数器来累计1的个数,这样就可以用来更新结果res了,就不用把每个中间结果都保存下来了,参见代码如下:
解法三:
class Solution {
public:
int longestLine(vector<vector<int>>& M) {
if (M.empty() || M[].empty()) return ;
int m = M.size(), n = M[].size(), res = ;
vector<vector<int>> dirs{{,},{,},{-,-},{-,}};
for (int i = ; i < m; ++i) {
for (int j = ; j < n; ++j) {
if (M[i][j] == ) continue;
for (int k = ; k < ; ++k) {
int cnt = , x = i, y = j;
while (x >= && x < m && y >= && y < n && M[x][y] == ) {
x += dirs[k][];
y += dirs[k][];
++cnt;
}
res = max(res, cnt);
}
}
}
return res;
}
};
参考资料:
https://discuss.leetcode.com/topic/87231/dfs-straightforward
https://discuss.leetcode.com/topic/87197/java-o-nm-time-dp-solution
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] Longest Line of Consecutive One in Matrix 矩阵中最长的连续1的更多相关文章
- LC 562. Longest Line of Consecutive One in Matrix
Given a 01 matrix M, find the longest line of consecutive one in the matrix. The line could be horiz ...
- LeetCode 562. Longest Line of Consecutive One in Matrix(在矩阵中最长的连续1)$
Given a 01 matrix M, find the longest line of consecutive one in the matrix. The line could be horiz ...
- Longest Line of Consecutive One in Matrix
Given a 01 matrix, find the longest line of consecutive 1 in the matrix. The line could be horizonta ...
- [LeetCode] Longest Increasing Path in a Matrix 矩阵中的最长递增路径
Given an integer matrix, find the length of the longest increasing path. From each cell, you can eit ...
- 329 Longest Increasing Path in a Matrix 矩阵中的最长递增路径
Given an integer matrix, find the length of the longest increasing path.From each cell, you can eith ...
- LeetCode All in One题解汇总(持续更新中...)
突然很想刷刷题,LeetCode是一个不错的选择,忽略了输入输出,更好的突出了算法,省去了不少时间. dalao们发现了任何错误,或是代码无法通过,或是有更好的解法,或是有任何疑问和建议的话,可以在对 ...
- [Leetcode] Longest consecutive sequence 最长连续序列
Given an unsorted array of integers, find the length of the longest consecutive elements sequence. F ...
- [LeetCode] Longest Consecutive Sequence 求最长连续序列
Given an unsorted array of integers, find the length of the longest consecutive elements sequence. F ...
- LeetCode——Longest Consecutive Sequence
LeetCode--Longest Consecutive Sequence Question Given an unsorted array of integers, find the length ...
随机推荐
- Oracle查看表空间大小和使用率
1. 全部表空间的大小select tablespace_name, sum(bytes)/1024/1024 from dba_data_files group by tablespace_name ...
- Linux下的指令:find,which
1. 在Linux系统下,使用find来查找文件: find [path] [condition] [operation] path指定了在哪个目录查找,condition限定了查找条件,operat ...
- Java基础学习笔记九 Java基础语法之this和super
构造方法 我们对封装已经有了基本的了解,接下来我们来看一个新的问题,依然以Person为例,由于Person中的属性都被private了,外界无法直接访问属性,必须对外提供相应的set和get方法.当 ...
- 201621123043 《Java程序设计》第9周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 泛型的定义: 泛型,即"参数化类型".一提到参数,最熟悉的就是定义方法时有形参,然后调用此 ...
- 【审核】检查iOS项目中是否使用了IDFA
(1)什么是IDFA 关于IDFA,在提交应用到App Store时,iTunes Connect有如下说明: 这里说到检查项目中是否包含IDFA,那如何来对iOS项目(包括第三方SDK)检查是否包含 ...
- python 面向对象之继承与派生
一:初识继承 1,什么是继承? 继承指的是类与类之间的关系,是一种什么"是"什么的关系,继承的功能之一就是用来解决代码重用问题 继承是一种创建新类的方式,在python中,新建的类 ...
- WebApi一个控制器中定义多个Get方法。
问题:怎样解决一个ApiController中定义多个Get方法或者Post方法? 答:要想实现一个ApiController中定义多个Get方法或者Post方法,则需要在WebApiConfig类中 ...
- 第三章Hibernate关联映射
第三章Hibernate关联映射 一.关联关系 类与类之间最普通的关系就是关联关系,而且关联是有方向的. 以部门和员工为列,一个部门下有多个员工,而一个员工只能属于一个部门,从员工到部门就是多对一关联 ...
- Python爬虫之urllib模块2
Python爬虫之urllib模块2 本文来自网友投稿 作者:PG-55,一个待毕业待就业的二流大学生. 看了一下上一节的反馈,有些同学认为这个没什么意义,也有的同学觉得太简单,关于Beautiful ...
- Python内置函数(22)——list
英文文档: class list([iterable]) Rather than being a function, list is actually a mutable sequence type, ...