Maximal Square - LeetCode 221

題目描述:

Given a 2D binary matrix filled with 0's and 1's, find the largest square containing all 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.
Credits:

Special thanks to @Freezen for adding this problem and creating all test cases.

Hide Tags Dynamic Programming

分析:
要找到全爲'1'的正方形最大面積,思路和64題的Minimum Path Sum很類似。從一個矩陣的左上方走到右下方,找到滿足條件的所有正方形,求得最大的一個即可。

這樣可以用一個二維數組dp[][]來存放計算過程中臨時最大值。其中dp[i][j]表示以matrix[i][j]爲右下角端點的全爲'1'的最大的方陣的邊長,那麼最後求出求出最大的邊長max,即可得到最大面積max * max。

那麼遞推公式是怎樣的呢?最暴力的方法就是動筆在紙上挨着畫幾個例子,歸納法找規律:

首先,但看第0行和第0列,由於沒有三個前向鄰居(每個元素的左邊、上變和左上的元素),而體重要求的是方陣的面積,因此對於dp第0行和第0列,直接等於matrix中的字符對應的數字即可。

然後問題來了,如何更新dp[i][j](i>0 && j>0)?
要計算全爲'1'的方陣,那麼
    當matrix[i][j]爲'0'時,以當前節點爲右下角節點時,最大的全爲'1'的方陣不存在,此時dp[i][j] = 0;
    當matrix[i][j]爲'1'時,如果當前節點位置對應的dp中節點左上相鄰的三個元素均均爲r,則dp[i][j] = r+1
          如果當前節點位置對應的dp中節點左上相鄰的三個元素不相等,那麼dp[i][j] = min(三個前向鄰居)+1
          合併起來就是dp[i][j] = min(dp[i-1][j-1],dp[i][j-1],dp[i-1][j]) + 1;
 

以下是C++實現代碼:

/**///////////////////////////12ms*/
class Solution {
public:
    int min(int a,int b,int c){ //返回三個數中最小值
        int tmp = a < b ? a:b;
        return (tmp < c) ? tmp : c;
    }
    int maximalSquare(vector<vector<char>>& matrix) {
        int m = matrix.size();
        if(m == 0) //爲空,則返回0
            return 0;
        int n = matrix[0].size();

        vector<vector<int>> dp(m,vector<int>(n,0)); //臨時二維數組
        int max = 0; //最大邊長變量
        for(int i = 0; i < m; i++){ //初始化第0列
            if(matrix[i][0] == '0' )
                 dp[i][0] = 0;
            else
                 dp[i][0] = 1;

            if(max < dp[i][0]) //同時更新最大邊長
                max = dp[i][0];
        }
   
        for(int j = 0; j < n; j++){ //初始化第0行
            if(matrix[0][j] == '0' )
                 dp[0][j] = 0;
            else
                 dp[0][j] = 1;

            if(max < dp[0][j]) //同時更新最大邊長
                max = dp[0][j];
        }

        for(int i = 1; i < m; i++){ //計算非0行和非0列元素作爲最右下角元素的全爲'1'的最大邊長
            for(int j = 1; j < n; j++){
                if(matrix[i][j] == '0' ) //matrix[i][j] == 0,那麼該位置對應的最大邊長爲0
                    dp[i][j] = 0;
                else{ matrix[i][j]==1的時候,用遞推公式迭代
                    dp[i][j] = min(dp[i-1][j-1],dp[i][j-1],dp[i-1][j]) + 1;

                    if(max < dp[i][j])   //更新最大邊長 
                        max = dp[i][j];
                }
            }
        }
        return max * max; //返回最大面積
    }
};


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章