DP statistical matrix series: 221. The largest square 1277. The square with all 1 statistics 1504. The matrix with all 1 statistics 1139. The largest square with 1 as the boundary

leetcode 221 largest square

Title description

In a two-dimensional matrix composed of 0 and 1, find the largest square containing only 1 and return its area.

Example

输入: 

1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0

输出: 4

Solution 2: Dynamic programming
For dynamic programming, in most cases we will define a two-dimensional array dp, then define the meaning of dp[i][j], and then derive dp[i][j] and dp[i-1] The relationship between [j], dp[i][j-1], dp[i-1][j-1]. Of course, the relationship between dp[i][j] and dp[i+1][j], dp[i][j+1], dp[i+1][j+1] can also be derived, Let's talk about how to solve this problem with dp.

1. First, we define dp[i][j] to mean the maximum side length of a square with dp[i][j] as the lower right corner.

2. Then we will deduce their relationship

Obviously, for any point dp[i][j], since the point is the lower right corner of the square, the right, lower, and lower right sides of the point don’t need to be considered. What we care about is the left, upper, and upper left, which is ours To derive the relationship between dp[i][j] and dp[i-1][j], dp[i][j-1], dp[i-1][j-1]. They have the following relationship

dp[i][j] = min( dp[i-1][j], dp[i-1][j-1], dp[i][j-1] )+ 1

This relationship is actually not difficult to infer, after all, there can be no 0, so we can only get the intersection of their three points. You can draw a picture, it might be easier to understand.

code show as below:

#include<cmath>
class Solution {
public:
    int maximalSquare(vector<vector<char>>& matrix) {
        if (matrix.size()==0 || matrix[0].size()==0) return 0;
        int row=matrix.size();
        int col=matrix[0].size();
        int maxlen=0;
        int dp[row+10][col+10];
        //或者int[][] dp = new int[rows + 10][cols + 10];好像不行。。。这是Java的写法
        memset(dp,0,sizeof(dp));

        for (int i=1;i<=row;i++)
            for (int j=1;j<=col;j++)
            if (matrix[i-1][j-1]=='1')
            {
                dp[i][j]=min(dp[i-1][j],min(dp[i][j-1],dp[i-1][j-1]))+1;
                if (dp[i][j]>maxlen) maxlen=dp[i][j];
            }
        return maxlen*maxlen;
    }
};



Time complexity: O(n*m)
Space complexity: O(n*m)
 


Original link: https://blog.csdn.net/m0_37907797/article/details/102914218

 

Wrote by the way

leetcode 1277 counts square sub-matrices with all ones

This question is very similar to 221. The largest square, and the method used is almost the same.

We use f[i][j] to denote the maximum side length of the square with (i, j) as the lower right corner, so in addition to this definition, f[i][j] = x also means (i, j) The number of squares in the lower right corner is x (that is, one square with sides 1, 2, ..., x). After calculating all f[i][j], we accumulate them to get the number of squares in the matrix.

#include<cmath>
class Solution {
public:
    int countSquares(vector<vector<int>>& matrix) {
        if (matrix.size()==0 || matrix[0].size()==0) return 0;
        int row=matrix.size();
        int col=matrix[0].size();
        int ans=0;
        int dp[row+10][col+10];
        //int[][] dp = new int[rows + 10][cols + 10];
        memset(dp,0,sizeof(dp));

        for (int i=1;i<=row;i++)
            for (int j=1;j<=col;j++)
            if (matrix[i-1][j-1]==1)
            {
                dp[i][j]=min(dp[i-1][j],min(dp[i][j-1],dp[i-1][j-1]))+1;
                ans+=dp[i][j];
            }
        //delete[] dp;
        return ans;
    }
};

 

Okay, let’s take a look at Youdao’s 196th weekly contest question:

leetcode 1504 count all 1 submatrices

Compared to 1277, the square has been changed to a rectangle, so it is difficult for us to determine the length and width of the 2-dimensional information by just relying on the lower right corner. We will save the 2-dimensional information separately, and then use the enumeration to fill the middle filling part.

class Solution {
public:
    int numSubmat(vector<vector<int>>& mat) {
        if (mat.size()==0 || mat[0].size()==0) return 0;
        int n=mat.size(),m=mat[0].size();
        //f[i][j][0]表示向左最长,f[i][j][1]表示向上最长
        int f[n+10][m+10][2];
        memset(f,0,sizeof(f));
        int ans=0;

        for (int i=1;i<=n;i++)
            for (int j=1;j<=m;j++)
            if (mat[i-1][j-1]==1)
            {
                f[i][j][0]=f[i][j-1][0]+1;
                f[i][j][1]=f[i-1][j][1]+1;
                int minlen=f[i][j][0];
                for (int k=i;k>=i-f[i][j][1]+1;k--)
                {
                    if (f[k][j][0]<minlen)
                        minlen=f[k][j][0];
                    ans+=minlen;
                }
            }
        return ans;
    }
};

One thing to note here is that you img2must remember to use the lower right corner as the standard, so it is not a simple accumulation of the length to the left. While going up, you must record the minimum length of minlen to the left to form a matrix.

 

4. Here I also added a question from the day02 of the dynamic programming question for easy understanding, because the code of the question above is adapted from this question.

leetcode 1139 The largest square bordered by 1

I thought of the idea. It’s similar to the square before. Use [i][j] as the bottom right corner to record two dp (the longest one goes to the right and the longest one goes up), and then from these two Choose a small one, enumerate the side length of this square from large to small , determine whether it is feasible, and record ans. (I wanted to record four edges, but found that only two edges are related to the lower right corner, and the edges are still not enumerated, so it is best to record two edges)

class Solution {
public:
    int largest1BorderedSquare(vector<vector<int>>& grid) {
        if (grid.size()==0 || grid[0].size()==0) return 0;
        int n=grid.size(),m=grid[0].size();
        int ans=0;
        //f[i][j][0]表示往左最长,f[i][j][1]表示往上最长
        int f[n+10][m+10][2];
        memset(f,0,sizeof(f));
        for (int i=1;i<=n;i++)
            for (int j=1;j<=m;j++)
            if (grid[i-1][j-1]==1)
            {
                f[i][j][0]=f[i][j-1][0]+1;
                f[i][j][1]=f[i-1][j][1]+1;
 
                int maxlen=f[i][j][0];
                if (f[i][j][1]<maxlen) maxlen=f[i][j][1];
                
                for (int k=maxlen;k>ans;k--)
                {
                    if (f[i][j-k+1][1]>=k && f[i-k+1][j][0]>=k)
                    {
                        ans=k;
                        break;
                    }
                }
            }
        return ans*ans;
            
    }
};

Reference from: https://leetcode-cn.com/problems/largest-1-bordered-square/solution/java-dong-tai-gui-hua-by-resolmi/

 

Comments are welcome to continue to add corresponding types of questions!

Guess you like

Origin blog.csdn.net/hbhhhxs/article/details/107290520