[LeetCode] 221. Maximal Square _ Medium Tag: Dynamic Programming
2018-07-17 06:44 Johnson_强生仔仔 阅读(259) 评论(0) 编辑 收藏 举报Given a 2D binary matrix filled with 0's and 1's, find the largest square containing only 1's and return its area.
Example:
Input: 1 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 0 0 1 0 Output: 4
思路是DP, 3种做法, 通用的T: O(m*n) , S: O(m*n) 和只针对部分情况可以use 滚动数组来reduce space成为O(n).
A[i][j] = min(A[i-1][j-1], left[i][j-1], up[i-1][j]) + 1 为边长 i, j > 0
滚动数组
A[i][j] = min(A[i-1][j-1], A[i][j-1], A[i-1][j]) + 1 为边长 i, j > 0
A[i][j] = min(A[i%2-1][j-1], A[i%2][j-1], A[i%2-1][j]) + 1 为边长 i, j > 0
1. Constraints
1) size >=[0*0]
2) element will be "1" or "0" # note it will be integer or string
2. Ideas
DP T: O(m*n) S: O(n) optimal
1) edge case, empty, m == 1 or n == 1
2) left, up , ans, init
3)
A[i][j] = min(A[i-1][j-1], left[i][j-1], up[i-1][j]) + 1
4) return res*res
3. codes
1) use left, up , and ans T: O(m*n) S: O(m*n)
1 class Solution: 2 def maxSquare(self, matrix): 3 if not matrix: return 0 4 m, n = len(matrix), len(matrix[0]) 5 left, up, ans, res = [[0]*n for _ in range(m)], [[0]*n for _ in range(m)], [[0]*n for _ in range(m)], 0 6 for i in range(m): 7 for j in range(n): 8 if matrix[i][j] == "1": 9 res = 1 # edge case when m == 1 or n == 1 10 if j == 0: 11 left[i][j] = ans[i][j] = 1 12 if i == 0: 13 up[i][j] = ans[i][j] = 1 14 if i >0 and j > 0: 15 left[i][j] = left[i][j-1] + 1 16 up[i][j] = up[i-1][j] + 1 17 for i in range(1, m): 18 for j in range(1, n): 19 if matrix[i][j] == "1": 20 ans[i][j] = min(ans[i-1][j-1], left[i][j-1], up[i-1][j])+1 21 res = max(res, ans[i][j]) 22 return res*res
3.2) skip left and up, just use f array
T: O(m*n) S: O(m*n)
class Solution: def maxSquare(self, matrix): if not matrix or not matrix[0]: return 0 m, n = len(matrix), len(matrix[0]) f, ans = [[0] * n for _ in range(m)], 0 # initial f for i in range(m): if matrix[i][0] == "1": f[i][0] = 1 ans = 1 # edge case when only edge is 1 for j in range(n): if matrix[0][j] == "1": f[0][j] = 1 ans = 1 for i in range(1, m): for j in range(1, n): if matrix[i][j] == "1": f[i][j] = min(f[i - 1][j], f[i][j - 1], f[i - 1][j - 1]) + 1 ans = max(ans, f[i][j]) return ans * ans
3.2.1) 将初始化都放在f赋值的两个for loop中:
T: O(m*n) S: O(m*n)
class Solution: def maxSquare(self, matrix): if not matrix or not matrix[0]: return 0 m, n = len(matrix), len(matrix[0]) f, ans = [[0] * n for _ in range(m)], 0 for i in range(m): for j in range(n): if matrix[i][j] == "1": if i == 0 or j == 0: f[i][j] = 1 else: f[i][j] = min(f[i - 1][j], f[i][j - 1], f[i - 1][j - 1]) + 1 ans = max(ans, f[i][j]) return ans * ans
3.3) 滚动数组, T: O(m*n), S: O(n)
class Solution: def maxSquare(self, matrix): if not matrix or not matrix[0]: return 0 m, n = len(matrix), len(matrix[0]) f, ans = [[0] * n for _ in range(2)], 0 for i in range(m): for j in range(n): if matrix[i][j] == "1": if i == 0 or j == 0: f[i % 2][j] = 1 else: f[i % 2][j] = min(f[(i - 1) % 2][j], f[i % 2][j - 1], f[(i - 1) % 2][j - 1]) + 1 ans = max(ans, f[i % 2][j]) else: f[i % 2][j] = 0 #Note: must notice when using rolling array, need to initial return ans * ans
4. Test cases
1) edge case
2)
1 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 0 0 1 0