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的更多相关文章

  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 ...

  2. 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 ...

  3. 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 ...

  4. [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 ...

  5. 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 ...

  6. LeetCode All in One题解汇总(持续更新中...)

    突然很想刷刷题,LeetCode是一个不错的选择,忽略了输入输出,更好的突出了算法,省去了不少时间. dalao们发现了任何错误,或是代码无法通过,或是有更好的解法,或是有任何疑问和建议的话,可以在对 ...

  7. [Leetcode] Longest consecutive sequence 最长连续序列

    Given an unsorted array of integers, find the length of the longest consecutive elements sequence. F ...

  8. [LeetCode] Longest Consecutive Sequence 求最长连续序列

    Given an unsorted array of integers, find the length of the longest consecutive elements sequence. F ...

  9. LeetCode——Longest Consecutive Sequence

    LeetCode--Longest Consecutive Sequence Question Given an unsorted array of integers, find the length ...

随机推荐

  1. [poj3252]Round Numbers_数位dp

    Round Numbers poj3252 题目大意:求一段区间内Round Numbers的个数. 注释:如果一个数的二进制表示中0的个数不少于1的个数,我们就说这个数是Round Number.给 ...

  2. 查看Linux内核版本之lsb_release

    lsb_release命令LSB是Linux Standard Base的缩写,lsb_release命令用来显示LSB和特定版本的相关信息,可通过yum -y install redhat-lsb命 ...

  3. js 声明提升

    声明提前变量在声明之前已经可以使用了 js中的所有的变量声明都提升到函数体内的顶部 ,如下图 实际运行的情况是如下 function f1() {-- var scope ; console.log( ...

  4. 第一次作业:扑通扑通 我的IT

    让我掉下眼泪的不止昨夜的酒,还有这满屏的代码. 第一部分:结缘计算机 你为什么选择计算机专业?你认为你的条件如何?和这些博主比呢? 在炎炎的夏日,伴随这高三的结束,我也面临大学专业的选择,我看着书里密 ...

  5. 异步协程 的 trip库

    import trip headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, ...

  6. velocity学习总结

    什么是velocity velocity是一个基于Java的模板引擎,它可以实现彻底的前后端,前端不允许像jsp那样出现Java代码,而是利用context容器传递变量,在java代码里面我们可以往容 ...

  7. php的api及登录的权限验证

    类,库,接口(APi),函数,这些概念都是根据问题规模的大小来界定的.一个很小的问题肯定没有必要写成一个库,只需要写几句话就行了. 但是比如一个登录验证,这个功能很强大,很通用,可能前台后台都需要用到 ...

  8. Service Worker和HTTP缓存

    很多人,包括我自己,初看Service Worker多一个Cache Storage的时候,就感觉跟HTTP长缓存没什么区别. 例如大家讲的最多的Service Worker能让网页离线使用,但熟悉H ...

  9. 《网络》:设置三个密码:通过console口连接设备,进入特权模式,登录Telnet

    软件:Cisco Packet Tracer Instructor 软件下载链接在上一篇文章中. 内容:通过设置三个密码,熟悉采用Telnet方式配置交换机的方法. 细节说明:计算机的IP地址和交换机 ...

  10. Python内置函数(8)——bool

    英文文档: class bool([x]) Return a Boolean value, i.e. one of True or False. x is converted using the st ...