1. 程式人生 > >leetcode 221. Maximal Square 最大正方形面積 + 動態規劃DP實現

leetcode 221. Maximal Square 最大正方形面積 + 動態規劃DP實現

Given a 2D binary matrix filled with 0’s and 1’s, find the largest square containing only 1’s and return its area.

For example, given the following matrix:

1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0
Return 4.

原以為是DFS深度優先遍歷,後來一想,這個是求最大的正方形的面積,DFS似乎解決不了問題。後來我一直想著使用DFS解決問題,但是想不出來,後來網上看到了一個DP做法,這個方法十分的棒。

這個一個很基本的動態規劃DP的做法,必須要會做

主要思路如下:當我們判斷以某個點為正方形右下角時最大的正方形時,那它的上方,左方和左上方三個點也一定是某個正方形的右下角,否則該點為右下角的正方形最大就是它自己了。這是定性的判斷,那具體的最大正方形邊長呢?我們知道,該點為右下角的正方形的最大邊長,最多比它的上方,左方和左上方為右下角的正方形的邊長多1,最好的情況是是它的上方,左方和左上方為右下角的正方形的大小都一樣的,這樣加上該點就可以構成一個更大的正方形。

但如果它的上方,左方和左上方為右下角的正方形的大小不一樣,合起來就會缺了某個角落,這時候只能取那三個正方形中最小的正方形的邊長加1了。

s假設dpi表示以i,j為右下角的正方形的最大邊長,則有

dp[i][j] = min(dp[i-1][j-1], dp[i-1][j], dp[i][j-1]) + 1
dp[i][j]表示已(i,j)為右下角的正方形的最大的邊長

程式碼如下:

/*
 * 當我們判斷以某個點為正方形右下角時最大的正方形時,那它的上方,左方和左上方三個點也一定
 * 是某個正方形的右下角,否則該點為右下角的正方形最大就是它自己了。這是定性的判斷,
 * 那具體的最大正方形邊長呢?我們知道,該點為右下角的正方形的最大邊長,最多比它的上方,
 * 左方和左上方為右下角的正方形的邊長多1,最好的情況是是它的上方,左方和左上方為右下角的
 * 正方形的大小都一樣的,這樣加上該點就可以構成一個更大的正方形。 
 * 
 * 但如果它的上方,左方和左上方為右下角的正方形的大小不一樣,合起來就會缺了某個角落,
 * 這時候只能取那三個正方形中最小的正方形的邊長加1了。
 * s假設dpi表示以i,j為右下角的正方形的最大邊長,則有
 * dp[i
][j] = min(dp[i-1][j-1], dp[i-1][j], dp[i][j-1]) + 1 * * dp[i][j]表示已(i,j)為右下角的正方形的最大的邊長 * * */ public class Solution { public int maximalSquare(char[][] matrix) { if(matrix==null || matrix.length<=0) return 0; int [][]dp=new int[matrix.length][matrix[0].length]; //注意res的初始化 int res=0; for(int i=0;i<matrix.length;i++) { if(matrix[i][0]=='1') { dp[i][0]=1; res=1; }else dp[i][0]=0; } for(int i=0;i<matrix[0].length;i++) { if(matrix[0][i]=='1') { dp[0][i]=1; res=1; }else dp[0][i]=0; } for(int i=1;i<matrix.length;i++) { for(int j=1;j<matrix[0].length;j++) { if(matrix[i][j]=='0') dp[i][j]=0; else { dp[i][j] = Math.min(dp[i-1][j-1], Math.min(dp[i-1][j],dp[i][j-1])) + 1; res = Math.max(res, dp[i][j]); } } } //因為res是最大邊長,所以邊長的平方就是面積 return res*res; } }

下面是C++的做法,就是一個簡單的DP,很棒的做法

程式碼如下:

#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <map>

using namespace std;


class Solution
{
public:
    int maximalSquare(vector<vector<char>>& mat)
    {
        if (mat.size() <= 0)
            return 0;
        int res = 0;
        vector<vector<int>> dp(mat.size(), vector<int>(mat[0].size(), 0));
        for (int i = 0; i < mat.size(); i++)
        {
            if (mat[i][0] == '1')
            {
                dp[i][0] = 1;
                res = 1;
            }
            else
                dp[i][0] = 0;
        }
        for (int i = 0; i < mat[0].size(); i++)
        {
            if (mat[0][i] == '1')
            {
                dp[0][i] = 1;
                res = 1;
            }
            else
                dp[0][i] = 0;
        }


        for (int i = 1; i < mat.size(); i++)
        {
            for (int j = 1; j < mat[0].size(); j++)
            {
                if (mat[i][j] == '1')
                {
                    dp[i][j] = min(dp[i - 1][j], min(dp[i - 1][j - 1], dp[i][j - 1])) + 1;
                    res = max(res, dp[i][j]);
                }
                else
                    dp[i][j] = 0;
            }
        }

        return res*res;

    }
};