题目
难度:★★★★☆
类型:二维数组
方法:动态规划
在一个由 0 和 1 组成的二维矩阵内,找到只包含 1 的最大正方形,并返回其面积。
示例:
输入:
1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0
输出: 4
解答
方法1:暴力求解
如果采用暴力求解方法,可以遍历每一个位置,然后判断以该位置为左上角的最大正方形的大小,通过一层一层添加的方式寻找以该点为左上角的正方形面积极限。
class Point:
def __init__(self, loc):
self.h = loc[0]
self.w = loc[1]
self.value = loc
@property
def next_left(self):
return Point((self.h, self.w-1))
@property
def next_right(self):
return Point((self.h, self.w+1))
@property
def next_top(self):
return Point((self.h-1, self.w))
@property
def next_down(self):
return Point((self.h+1, self.w))
def get_half_circle(self, layer=1):
"""
获取右下角方向的所有相邻元素,第layer层
:return:
"""
start_point = Point((self.h, self.w+layer))
res = [start_point]
# 竖着的一列
for r in range(self.h+1, self.h+layer+1, 1):
res.append(Point((r, self.w+layer)))
# 横着的一列
for c in range(self.w+layer-1, self.w-1, -1):
res.append((Point((self.h+layer, c))))
return res
class Board:
def __init__(self, value):
assert value is not None and value[0] is not None, 'Not a board.'
self.value = value
self.height = len(value)
self.width = len(value[0])
def get_value(self, point):
if self.is_valid_point(point):
return self.value[point.h][point.w]
def set_value(self, point, value):
if self.is_valid_point(point):
self.value[point.h][point.w] = value
def is_valid_point(self, point):
return 0 <= point.h < self.height and 0 <= point.w < self.width
def find_square(self, point, value='1'):
"""
获得以point为左上角的最大正方形的边长
:param point:
:param value:
:return:
"""
assert isinstance(point, Point)
max_edge = 0
while True:
for test_point in point.get_half_circle(max_edge):
if self.get_value(test_point) != value:
return max_edge
max_edge += 1
class Solution:
def maximalSquare(self, matrix):
if not matrix or not matrix[0]:
return 0
board = Board(matrix)
res = 0
for h in range(board.height):
for w in range(board.width):
cur_edge = board.find_square(Point((h, w)), '1')
res = max(res, cur_edge)
return res ** 2
方法2:动态规划
可以使用动态规划解决这个问题,设输入matrix的高和宽分别为height和width,定义一个同样维度的dp矩阵,该矩阵中的某一点p(h,w)处的值dp[h][w]表示以p点为右下角的最大正方形的边长。
定义初始条件,对于第一行和第一列,dp矩阵中的数值取决于该点处的值是否为1,如果是设置为1,否则设置为0.
递推关系式。这个比较重要,点(h,w)处dp的值的计算需要(h-1,w),(h,w-1)和(h-1,w-1)三个点在dp处的值一起计算,公式为:
dp[h][w] = min(dp[h-1][w], dp[h][w-1], dp[h-1][w-1]) + 1
因为当前点能否组成正方形是由左上角三个点的能组成的最小的正方形决定的。
最后定义一个变量,用于存储计算过程中出现的最大正方形的边长。
一个例子,
matrix = [["1","0","1","0","0"],
["1","0","1","1","1"],
["1","1","1","1","1"],
["1","0","0","1","0"]]
得到的dp矩阵为:
[[1, 0, 1, 0, 0],
[1, 0, 1, 1, 1],
[1, 1, 1, 2, 2],
[1, 0, 0, 1, 0]]
class Solution:
def maximalSquare(self, matrix):
if not matrix or not matrix[0]:
return 0
height, width = len(matrix), len(matrix[0])
dp = [[0 for _ in range(width)] for _ in range(height)]
max_edge = 0
for h in range(height):
for w in range(width):
if matrix[h][w] == '1':
if h == 0 or w == 0:
dp[h][w] = 1
else:
dp[h][w] = min(dp[h-1][w], dp[h][w-1], dp[h-1][w-1]) + 1
else:
dp[h][w] = 0
max_edge = max(max_edge, dp[h][w])
return max_edge ** 2
如有疑问或建议,欢迎评论区留言~