這道題主要是利用動態規劃,注意好邊界條件,就能夠解決。
<!-- more -->git
在一個由 0 和 1 組成的二維矩陣內,找到只包含 1 的最大正方形,並返回其面積。github
示例:segmentfault
輸入: 1 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 0 0 1 0 輸出: 4
原題url:https://leetcode-cn.com/probl...數組
這道題應該很快會讓咱們想起使用動態規劃,從左上角往右下角開始找。優化
假設咱們用一個二維數組dp
,記錄每個位置所能構成的最大正方形的邊長(從左上角開始算)。位置(i, j)
是 1,則其可能構成的正方形的邊長是Min(dp(i - 1, j - 1), dp(i - 1, j), dp(i, j - 1)) + 1
。看到這個,相信你也會理解了,每個位置所能構成的最大邊長的條件,實際上是要求包圍着它的左上角三個位置都是 1 才能夠。url
一直遞推回到最初點,也就意味着,第一行和第一列須要單獨判斷。spa
以前應該也有作過相似空間複雜度上的優化,咱們真的須要一個真正的二維數據dp
來記錄中間結果嗎?其實咱們發現,當一個位置用過以後,這個位置自己的數字已經再也不重要,關鍵是該位置所能構成的最大正方形的邊長,也就是咱們記錄的中間結果。所以能夠直接更新原數組上的數字。code
還有就是須要考慮一些特殊狀況,好比只有一行或者一列的時候,咱們應該如何作。內存
接下來讓咱們看看代碼:leetcode
class Solution { public int maximalSquare(char[][] matrix) { // 高 int height = matrix.length; if (height == 0) { return 0; } // 寬 int width = matrix[0].length; // 檢查第一行和第一列,是否有'1' int result = checkFirstRowAndCol(matrix, height, width); // 只有一行或一列,或者只有一個 if (height == 1 || width == 1) { return result; } // result如今作爲記錄最大邊的長度 // 中間結果 int temp; for (int i = 1; i < height; i++) { for (int j = 1; j < width; j++) { if (matrix[i][j] == '0') { continue; } // 求出matrix[i - 1][j - 1]、matrix[i - 1][j]、matrix[i][j - 1]中的最小值 temp = matrix[i - 1][j] < matrix[i][j - 1] ? matrix[i - 1][j] : matrix[i][j - 1]; temp = temp < matrix[i - 1][j - 1] ? temp : matrix[i - 1][j - 1]; // 更新當前節點的值 matrix[i][j] = (char) (temp + 1); temp = temp + 1 - '0'; if (result < temp) { result = temp; } } } return result * result; } private int checkFirstRowAndCol(char[][] matrix, int height, int width) { // 檢查第一列 for (int i = 0; i < height; i++) { if (matrix[i][0] == '1') { return 1; } } // 檢查第一行 for (int i = 0; i < width; i++) { if (matrix[0][i] == '1') { return 1; } } return 0; } }
提交OK,執行用時:5 ms
,內存消耗:41.1 MB
。
上面的這個代碼,我並非一次性就直接寫出來的,也是在不斷的提交中,發現有一些特殊狀況沒有考慮,幸運的是力扣會每次提交完以後會告訴我不知足時的輸入的是什麼樣的,但這也會讓我常常考慮不足,還須要努力。
以上就是這道題目個人解答過程了,不知道你們是否理解了。這道題目利用動態規劃其實就差很少了,但重點仍是在於特殊狀況的判斷,須要注意。
有興趣的話能夠訪問個人博客或者關注個人公衆號、頭條號,說不定會有意外的驚喜。
公衆號:健程之道