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. 暴力搜索
分别从水平方向,竖直方向,对角线和反对角线计算。
class Solution {
public:
int longestLine(vector<vector<int>>& M) {
int max1=0;
int i,j,m=M.size();
if(!m) return 0;
int n=M[0].size();
for(i=0;i<m;i++){
int b=0;
for(j=0;j<n;j++)
if(M[i][j]==1) {
b++;
max1=max(max1,b);
}
else b=0;
}
for(i=0;i<n;i++){
int b=0;
for(j=0;j<m;j++)
if(M[j][i]==1) {
b++;
max1=max(max1,b);
}
else b=0;
}
//对角线
for(i=0;i<m;i++){
int b=0;j=0;int x=i;
while(x<m&&j<n){
if(M[x][j]==1) {
b++;
max1=max(max1,b);
}
else b=0;
x++;j++;
}
}
for(j=1;j<n;j++){
int b=0;i=0;int y=j;
while(i<m&&y<n){
if(M[i][y]==1) {
b++;
max1=max(max1,b);
}
else b=0;
i++;y++;
}
}
//反对角线
for(j=0;j<n;j++){
int b=0;i=0;int y=j;
while(i>=0&&i<m&&y>=0&&y<n){
if(M[i][y]==1) {
b++;
max1=max(max1,b);
}
else b=0;
y--;i++;
}
}
for(i=1;i<m;i++){
int b=0;j=n-1;int x=i;
while(x<m&&j>=0){
if(M[x][j]==1) {
b++;
max1=max(max1,b);
}
else b=0;
j--;x++;
}
}
return max1;
}
};
2. 3维的动态规划
定义一个
m∗n∗4
的数组空间,分别用来记录四个不同方向的连续1的个数。当遍历到元素M[i][j]时,dp[i][j][0]代表以M[i][j]为最右下角元素时,所得到的水平方向连续1的个数,其他以此类推。
以
[0,1,1,0],
[0,1,1,0],
[0,0,0,1], 为例。
dp[0]代表水平方向, dp[1]代表竖直方向,dp[2]代表对角线方向,dp[3]代表反对角线方向。
int longestLine(vector<vector<int>>& M) {
int max1=0;
int i,j,m=M.size();
if(!m) return 0;
int n=M[0].size();
vector<vector<vector<int>>> dp(m,vector<vector<int>> (n,vector<int>(4,0)));
for(i=0;i<m;i++){
for(j=0;j<n;j++){
if(M[i][j]==1){
dp[i][j][0]=j>0?dp[i][j-1][0]+1:1;
dp[i][j][1]=i>0?dp[i-1][j][1]+1:1;
dp[i][j][2]=(j>0&&i>0)?dp[i-1][j-1][2]+1:1;
dp[i][j][3]=(i>0&&j<n-1)?dp[i-1][j+1][3]+1:1;
}
max1=max(max1,max(dp[i][j][0],max(dp[i][j][1],max(dp[i][j][2],dp[i][j][3]))));
}
}
return max1;
}
时间复杂度:
O(m∗n)
空间复杂度:
O(m∗n)
3. 2维的动态规划
观察2中动态规划的解过程,可以发现当前行的dp只依赖于其前一行的dp值。因此可以只用一个二维的 n∗4 的空间记录即可。
j-1列 | j列 | j+1列 | ……. |
---|---|---|---|
2 | 1 | 3 | ……. |
0 | 待处理位置 | ….. |
当你遍历到待处理位置时,此时的dp[][]存储的是它的上一行的dp状态,因为dp的长度为n,2位置除外。此时,
dp[j][0]取决于0位置的dp[j-1][0];(水平)
dp[j][1]取决于1位置的dp[j][1];(竖直)
dp[j][2]取决于2位置的dp[j][2],这里用old表示。因为当前的dp[j][2]是下一个位置要用到的old,记得保存;(正对角线)
dp[j][3]取决于3位置的dp[j+1][3]。(反对角线)
class Solution {
public:
int longestLine(vector<vector<int>>& M) {
int max1=0;
int i,j,m=M.size();
if(!m) return 0;
int n=M[0].size();
vector<vector<int>> dp(n,vector<int>(4,0));
for(i=0;i<m;i++){
int old=0;
for(j=0;j<n;j++){
if(M[i][j]==1){
dp[j][0]=j>0?dp[j-1][0]+1:1;
dp[j][1]=i>0?dp[j][1]+1:1;
int pre=dp[j][2];
dp[j][2]=(j>0&&i>0)?old+1:1;
old=pre;
dp[j][3]=(i>0&&j<n-1)?dp[j+1][3]+1:1;
}else{
old=dp[j][2];
dp[j][0]=dp[j][1]=dp[j][2]=dp[j][3]=0;
}
max1=max(max1,max(dp[j][0],max(dp[j][1],max(dp[j][2],dp[j][3]))));
}
}
return max1;
}
};
时间复杂度:
O(m∗n)
空间复杂度:
O(n)