給定乙個僅包含 0 和 1 的二維二進位制矩陣,找出只包含 1 的最大矩形,並返回其面積。
示例:
輸入:
[ ["1","0","1","0","0"],
["1","0","1","1","1"],
["1","1","1","1","1"],
["1","0","0","1","0"]
]輸出: 6
1 使用柱狀圖的優化暴力方法
設定二維陣列dp
,dp[i][j]
表示以該座標結束的矩形的最大可能寬度。
dp[i][j] = dp[i][j-1] + 1 if matrix[i][j] == '1'
一旦我們知道每個點對應的最大寬度,就可以以線性時間內計算出以該點為右下角的最大矩形。我們從該位置第i
行往上遍歷該列,可以得到從初始點(i,j)到當前點矩形的最大寬度,就是我們遇到的每個最大寬度d[k][j]的最小值。
我們定義
currentwidth = max(currentwidth, dp[i][k])
currentarea = currentwidth * (i - k + 1)
maxarea = max(maxarea, currentarea)
對每個點重複這一過程,就可以得到全域性最大。
注意,我們預計算最大寬度的方法事實上將輸入轉化成了一系列的柱狀圖,每一欄是乙個新的柱狀圖。我們在針對每個柱狀圖計算最大面積。
於是,上述方法本質上是84 - 柱狀圖中最大的矩形題中優化暴力演算法的復用。
複雜度分析
時間複雜度:o(m
2n)o(m^2n)
o(m2n)
空間複雜度:o(m
n)o(mn)
o(mn
)m,n為輸入矩陣的行列數
2 動態規劃-每個點的最大高度
想象乙個演算法,對於每個點我們會通過以下步驟計算乙個矩形:
不斷向上方遍歷,直到遇到「0」,以此找到矩形的最大高度。
向左右兩邊擴充套件,直到無法容納矩形最大高度。
例如,找到黃色點對應的矩形:
我們知道,最大矩形必為用這種方式構建的矩形之一。
給定乙個最大矩形,其高為h
, 左邊界l
,右邊界r
,在矩形的底邊,區間[l, r]
內必然存在一點,其上連續1的個數(高度)<=h
。若該點存在,則由於邊界內的高度必能容納h
,以上述方法定義的矩形會向上延伸到高度h
,再左右擴充套件到邊界[l, r]
,於是該矩形就是最大矩形。
若不存在這樣的點,則由於[l, r]
內所有的高度均大於h
,可以通過延伸高度來生成更大的矩形,因此該矩形不可能最大。
綜上,對於每個點,只需要計算h
,l
,和r
- 矩形的高,左邊界和右邊界。
演算法
給定一行matrix[i]
,我們通過定義三個陣列height
,left
,和right
來記錄每個點的h
,l
,和r
。height[j]
對應matrix[i][j]
的高,以此類推。
問題轉化為如何更新每個陣列。
height:
這個比較容易。h
的定義是從該點出發連續的1的個數。
row[j] = row[j - 1] + 1 if row[j] == '1'
只需要一點改動即可:
new_height[j] = old_height[j] + 1 if row[j] == '1' else 0
left:考慮哪些因素會導致矩形左邊界的改變。由於當前行之上的全部0
已經考慮在當前版本的left
中,唯一能影響left
就是在當前行遇到0
。
因此我們可以定義:
new_left[j] = max(old_left[j], cur_left)
cur_left是我們遇到的最右邊的0的序號加1。當我們將矩形向左 「擴充套件」 ,我們知道,不能超過該點,否則會遇到0。
right:
我們可以沿用left
的思路,定義:
new_right[j] = min(old_right[j], cur_right)
cur_right
是我們遇到的最左邊的0的序號。簡便起見,我們不把cur_right
減去1 (就像我們給cur_left
加上1那樣) ,這樣我們就可以用height[j] * (right[j] - left[j])
而非height[j] * (right[j] + 1 - left[j])
來計算矩形面積。
這意味著, 嚴格地說 ,矩形的底邊由半開半閉區間[l, r)
決定,而非閉區間[l, r]
,且right
比右邊界大1。儘管不這樣做演算法也可以正確執行,但這樣會讓計算看起來更簡潔。
注意,為了正確的記錄cur_right
,我們需要從右向左迭代。因此,更新right
時需要從右向左。
一旦left
,right
,和height
陣列能夠正確更新,我們就只需要計算每個矩形的面積。
由於我們知道矩形j
的邊界和高,可以簡單地用height[j] * (right[j] - left[j])
來計算面積,若j的面積 大於max_area
,則更新之。
複雜度分析
時間複雜度:o(m
n)o(mn)
o(mn
)空間複雜度:o(n
)o(n)
o(n)
m,n為輸入矩陣的行列數
/*
* 動態規劃
* 時間複雜度o(mn) 空間複雜度o(n)
* m,n為陣列行列數
*/class
solutionii
// 更新left
for(
int j =
0; j < cols;
++j)
}// 更新right
for(
int j = cols-
1; j >=0;
--j)
}// 更新最大面積
LeetCode 85 最大矩形
給定乙個僅包含 0 和 1 的二維二進位制矩陣,找出只包含 1 的最大矩形,並返回其面積。示例 輸入 1 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 0 0 1 0 輸出 6此題和上一題的擴充套件,此題給的二維矩陣的每一行向上都形成了乙個直方圖,所以二維矩陣有多少行,就有多少個直方圖...
leetcode85 最大矩形
1.轉換成直方圖的做法 參考 利用leetcode84中的方法來做 首先要將給定的01矩陣轉換成84中的直方圖的樣子。每一行都對應乙個直方圖,且下一行直方圖是由上一行直方圖計算得到的。如果是0,則當前直方圖高為0,如果是1,則當前直方圖高度是上一層對應位置高度 1 1 0 1 0 0 1,0 1,0...
LeetCode 85 最大矩形
給定乙個僅包含 0 和 1 的二維二進位制矩陣,找出只包含 1 的最大矩形,並返回其面積。示例 輸入 1 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 0 0 1 0 輸出 6這一題的演算法本質上和84題largest rectangle in histogram一樣,對每一列都求出每...