# 562. Longest Line of Consecutive One in Matrix

**<font color=red>难度: Medium</font>**

## 刷题内容

> 原题连接

* https://leetcode.com/problems/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 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
******- 时间复杂度: O(row * col)******- 空间复杂度: O(1)******

本来打算取巧，直接用485题的代码+numpy模块，结果超时


因为求diagonal和anti-diagonal太慢了

```
from numpy import *
class Solution(object):
    def longestLine(self, M):
        """
        :type M: List[List[int]]
        :rtype: int
        """ 
        row = len(M)
        col = len(M[0]) if row else 0
        if not row:
            return 0
        
        res = -sys.maxsize
        for r in M:
            res = max(res, self.findMaxConsecutiveOnes(r))
        for c in zip(*M):
            res = max(res, self.findMaxConsecutiveOnes(c))
        for i in range(1-row, col):
            res = max(res, self.findMaxConsecutiveOnes(diag(M,i)))
        for i in range(1-col, row):
            res = max(res, self.findMaxConsecutiveOnes(diag(fliplr(M), i)))
        return res
            
    def findMaxConsecutiveOnes(self, nums):
        return len(max(''.join(map(str, nums)).split('0')))
```





> 思路 2
******- 时间复杂度: O(row * col)******- 空间复杂度: O(1)******


只好来一个暴力sb写法了，但是horizontal和vertical还是可以取巧

beats 64.43%


```python
class Solution(object):
    def longestLine(self, M):
        """
        :type M: List[List[int]]
        :rtype: int
        """ 
        row = len(M)
        col = len(M[0]) if row else 0
        if not row:
            return 0
        
        def findMaxConsecutiveOnes(nums):
            return len(max(''.join(map(str, nums)).split('0')))
        
        res = -sys.maxsize
        for r in M: # horizontal
            res = max(res, findMaxConsecutiveOnes(r))
        for c in zip(*M): # vertical
            res = max(res, findMaxConsecutiveOnes(c))
        i = 0
        while i < max(row, col): # upper diagonal
            cnt = 0
            x, y = 0, i
            while x < row and y < col:
                cnt = cnt + 1 if M[x][y] else 0
                res = max(res, cnt)
                x, y = x + 1, y + 1
            i += 1
        i = 1
        while i < max(row, col): # lower diagonal
            cnt = 0
            x, y = i, 0
            while x < row and y < col:
                cnt = cnt + 1 if M[x][y] else 0
                res = max(res, cnt)
                x, y = x + 1, y + 1
            i += 1
        i = 0
        while i < max(row, col): # upper anti-diagonal
            cnt = 0
            x, y = 0, col - i - 1
            while x < row and y >= 0:
                cnt = cnt + 1 if M[x][y] else 0
                res = max(res, cnt)
                x, y = x + 1, y - 1
            i += 1
        i = 1
        while i < max(row, col): # lower anti-diagonal
            cnt = 0
            x, y = i, col - 1
            while x < row and y >= 0:
                cnt = cnt + 1 if M[x][y] else 0
                res = max(res, cnt)
                x, y = x + 1, y - 1
            i += 1
        return res
```







> 思路 3
******- 时间复杂度: O(row * col)******- 空间复杂度: O(col)******


DP

- dp[j][0] horizontal
- dp[j][1] vertical
- dp[j][2] diagonal
- dp[j][3] anti-diagonal

beat 86.56%

```python
class Solution(object):
    def longestLine(self, M):
        """
        :type M: List[List[int]]
        :rtype: int
        """ 
        row = len(M)
        col = len(M[0]) if row else 0
        if not row:
            return 0
        
        dp = [[0]* 4 for _ in range(col)]
        res = 0
        for i in range(row):
            cur_dp = [[0] * 4 for _ in range(col)]
            for j in range(col):
                if M[i][j] == 1:
                    cur_dp[j][0] = cur_dp[j-1][0] + 1
                    cur_dp[j][1] = dp[j][1] + 1
                    cur_dp[j][2] = dp[j-1][2] + 1 if j - 1 >= 0 else 1
                    cur_dp[j][3] = dp[j+1][3] + 1 if j + 1 <= col - 1 else 1
                    res = max(res, max(cur_dp[j]))
            dp = cur_dp
        return res
```




> 思路 4
******- 时间复杂度: O(row * col)******- 空间复杂度: O(1)******

我们只要遍历一遍整个矩阵，遇到1的时候，如果我们确定这个1是某个方向的一个起始点的话，
起始点的意思就是说对于这个点，比如他是horizaontal的第一个1，或者是diagonal的第一个点

那么如果这个点是1且在边界上的话它肯定是起始点，否则它必须满足在这个方向上它的前一个点为0，这样它才是第一个1

然后确定了是某个方向的起始点之后，就沿着方向往下走到黑，并且更新连续1的个数，断掉的时候更新res


beats 25.69%

```python
class Solution(object):
    def longestLine(self, M):
        """
        :type M: List[List[int]]
        :rtype: int
        """ 
        row = len(M)
        col = len(M[0]) if row else 0
        if not row:
            return 0
        
        # horizontal, vertical, diagonal or anti-diagonal 
        dires = [[0,1], [1,0], [1,1], [1,-1]]
        res = 0
        for r in range(row):
            for c in range(col):
                if M[r][c]:
                    for d in range(4):
                        if self.isStartPoint(r, c, M, dires, d):
                            tmp_r, tmp_c = r, c
                            one_in_this_dire = 0
                            while 0 <= tmp_r < row and 0 <= tmp_c < col and M[tmp_r][tmp_c]:
                                one_in_this_dire += 1
                                tmp_r += dires[d][0]
                                tmp_c += dires[d][1]
                            res = max(res, one_in_this_dire)
        return res
    
    def isStartPoint(self, r, c, M, dires, d):
        prev_r, prev_c = r - dires[d][0], c - dires[d][1] # # prev point in its direction
        if prev_r < 0 or prev_c < 0 or prev_c > len(M[0]) - 1: # if boundary then True
            return True
        return M[prev_r][prev_c] == 0 # is the first one in this direction?
```

































