From 0966f4e7fde4a1f15eaca5d1213ff8e720e95bb5 Mon Sep 17 00:00:00 2001 From: Shubham Kondekar <40213815+kondekarshubham123@users.noreply.github.com> Date: Wed, 26 Oct 2022 19:41:48 +0530 Subject: [PATCH 1/6] Create largest_square_area_in_matrix.py --- matrix/largest_square_area_in_matrix.py | 187 ++++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 matrix/largest_square_area_in_matrix.py diff --git a/matrix/largest_square_area_in_matrix.py b/matrix/largest_square_area_in_matrix.py new file mode 100644 index 000000000000..a3d38c83b920 --- /dev/null +++ b/matrix/largest_square_area_in_matrix.py @@ -0,0 +1,187 @@ +""" +Question: +Given a binary matrix mat of size n * m, find out the maximum size square +sub-matrix with all 1s. + +--- +Example 1: + +Input: +n = 2, m = 2 +mat = [[1, 1], + [1, 1]] + +Output: +2 + +Explaination: The maximum size of the square +sub-matrix is 2. The matrix itself is the +maximum sized sub-matrix in this case. +--- +Example 2 + +Input: +n = 2, m = 2 +mat = [[0, 0], + [0, 0]] +Output: 0 + +Explaination: There is no 1 in the matrix. + + +Approch: +We initialize another matrix (dp) with the same dimensions +as the original one initialized with all 0’s. + +dp_array(i,j) represents the side length of the maximum square whose +bottom right corner is the cell with index (i,j) in the original matrix. + +Starting from index (0,0), for every 1 found in the original matrix, +we update the value of the current element as + +dp_array(i,j)=dp_array(dp(i−1,j),dp_array(i−1,j−1),dp_array(i,j−1)) + 1. +""" + + +from typing import List + + +def largest_square_area_in_matrix_top_down_approch(rows: int, cols: int, mat: List[List[int]]) -> int: + """ + Function updates the largest_square_area[0], if recursive call found + square with maximum area. + + We arent using dp_array here, so the time complexity would be exponential. + + >>> largest_square_area_in_matrix_top_down_approch(2, 2, [[1,1], [1,1]]) + 2 + >>> largest_square_area_in_matrix_top_down_approch(2, 2, [[0,0], [0,0]]) + 0 + """ + + def update_area_of_max_square(row: int, col: int) -> int: + + # BASE CASE + if row >= rows or col >= cols: + return 0 + + right = update_area_of_max_square(row, col+1) + diagonal = update_area_of_max_square(row + 1, col + 1) + down = update_area_of_max_square(row + 1, col) + + if mat[row][col]: + sub_problem_sol = 1 + min([right, diagonal, down]) + largest_square_area[0] = max( + largest_square_area[0], sub_problem_sol) + return sub_problem_sol + else: + return 0 + + largest_square_area = [0] + update_area_of_max_square(0, 0) + return largest_square_area[0] + + +def largest_square_area_in_matrix_top_down_approch_with_dp(rows: int, cols: int, mat: List[List[int]]) -> int: + """ + Function updates the largest_square_area[0], if recursive call found + square with maximum area. + + We are using dp_array here, so the time complexity would be O(N^2). + + >>> largest_square_area_in_matrix_top_down_approch_with_dp(2, 2, [[1,1], [1,1]]) + 2 + >>> largest_square_area_in_matrix_top_down_approch_with_dp(2, 2, [[0,0], [0,0]]) + 0 + """ + def update_area_of_max_square_using_dp_array(row: int, col: int, dp_array: List[List[int]]) -> int: + if row >= rows or col >= cols: + return 0 + if dp_array[row][col] != -1: + return dp_array[row][col] + + right = update_area_of_max_square_using_dp_array(row, col+1, dp_array) + diagonal = update_area_of_max_square_using_dp_array( + row + 1, col + 1, dp_array) + down = update_area_of_max_square_using_dp_array(row + 1, col, dp_array) + + if mat[row][col]: + sub_problem_sol = 1 + min([right, diagonal, down]) + largest_square_area[0] = max( + largest_square_area[0], sub_problem_sol) + dp_array[row][col] = sub_problem_sol + return sub_problem_sol + else: + return 0 + + largest_square_area = [0] + dp_array = [[-1] * cols for _ in range(rows)] + update_area_of_max_square_using_dp_array(0, 0, dp_array) + + return largest_square_area[0] + + +def largest_square_area_in_matrix_bottom_up(rows: int, cols: int, mat: List[List[int]]) -> int: + """ + Function updates the largest_square_area, using bottom up approch. + + >>> largest_square_area_in_matrix_bottom_up(2, 2, [[1,1], [1,1]]) + 2 + >>> largest_square_area_in_matrix_bottom_up(2, 2, [[0,0], [0,0]]) + 0 + + """ + dp_array = [[0] * (cols + 1) for _ in range(rows+1)] + largest_square_area = 0 + for row in range(rows-1, -1, -1): + for col in range(cols-1, -1, -1): + + right = dp_array[row][col + 1] + diagonal = dp_array[row + 1][col + 1] + bottom = dp_array[row + 1][col] + + if mat[row][col] == 1: + dp_array[row][col] = 1 + min(right, diagonal, bottom) + largest_square_area = max(dp_array[row][col], + largest_square_area) + else: + dp_array[row][col] = 0 + + return largest_square_area + + +def largest_square_area_in_matrix_bottom_up_space_optimization(rows: int, cols: int, mat: List[List[int]]) -> int: + """ + Function updates the largest_square_area, using bottom up approch. with space optimization. + + >>> largest_square_area_in_matrix_bottom_up_space_optimization(2, 2, [[1,1], [1,1]]) + 2 + >>> largest_square_area_in_matrix_bottom_up_space_optimization(2, 2, [[0,0], [0,0]]) + 0 + """ + current_row = [0] * (cols + 1) + next_row = [0] * (cols + 1) + largest_square_area = 0 + for row in range(rows-1, -1, -1): + for col in range(cols-1, -1, -1): + + right = current_row[col + 1] + diagonal = next_row[col + 1] + bottom = next_row[col] + + if mat[row][col] == 1: + current_row[col] = 1 + min(right, diagonal, bottom) + largest_square_area = max( + current_row[col], largest_square_area) + else: + current_row[col] = 0 + next_row = current_row + + return largest_square_area + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + # print(largest_square_area_in_matrix_bottom_up(2, 2, [[1,1], [1,1]])) From bab28904ba233e4a60b4d3f6886cb220ab71a897 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 26 Oct 2022 14:15:14 +0000 Subject: [PATCH 2/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- matrix/largest_square_area_in_matrix.py | 50 ++++++++++++++----------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/matrix/largest_square_area_in_matrix.py b/matrix/largest_square_area_in_matrix.py index a3d38c83b920..3b27928c28d9 100644 --- a/matrix/largest_square_area_in_matrix.py +++ b/matrix/largest_square_area_in_matrix.py @@ -46,7 +46,9 @@ from typing import List -def largest_square_area_in_matrix_top_down_approch(rows: int, cols: int, mat: List[List[int]]) -> int: +def largest_square_area_in_matrix_top_down_approch( + rows: int, cols: int, mat: list[list[int]] +) -> int: """ Function updates the largest_square_area[0], if recursive call found square with maximum area. @@ -65,14 +67,13 @@ def update_area_of_max_square(row: int, col: int) -> int: if row >= rows or col >= cols: return 0 - right = update_area_of_max_square(row, col+1) + right = update_area_of_max_square(row, col + 1) diagonal = update_area_of_max_square(row + 1, col + 1) down = update_area_of_max_square(row + 1, col) if mat[row][col]: sub_problem_sol = 1 + min([right, diagonal, down]) - largest_square_area[0] = max( - largest_square_area[0], sub_problem_sol) + largest_square_area[0] = max(largest_square_area[0], sub_problem_sol) return sub_problem_sol else: return 0 @@ -82,7 +83,9 @@ def update_area_of_max_square(row: int, col: int) -> int: return largest_square_area[0] -def largest_square_area_in_matrix_top_down_approch_with_dp(rows: int, cols: int, mat: List[List[int]]) -> int: +def largest_square_area_in_matrix_top_down_approch_with_dp( + rows: int, cols: int, mat: list[list[int]] +) -> int: """ Function updates the largest_square_area[0], if recursive call found square with maximum area. @@ -94,21 +97,22 @@ def largest_square_area_in_matrix_top_down_approch_with_dp(rows: int, cols: int, >>> largest_square_area_in_matrix_top_down_approch_with_dp(2, 2, [[0,0], [0,0]]) 0 """ - def update_area_of_max_square_using_dp_array(row: int, col: int, dp_array: List[List[int]]) -> int: + + def update_area_of_max_square_using_dp_array( + row: int, col: int, dp_array: list[list[int]] + ) -> int: if row >= rows or col >= cols: return 0 if dp_array[row][col] != -1: return dp_array[row][col] - right = update_area_of_max_square_using_dp_array(row, col+1, dp_array) - diagonal = update_area_of_max_square_using_dp_array( - row + 1, col + 1, dp_array) + right = update_area_of_max_square_using_dp_array(row, col + 1, dp_array) + diagonal = update_area_of_max_square_using_dp_array(row + 1, col + 1, dp_array) down = update_area_of_max_square_using_dp_array(row + 1, col, dp_array) if mat[row][col]: sub_problem_sol = 1 + min([right, diagonal, down]) - largest_square_area[0] = max( - largest_square_area[0], sub_problem_sol) + largest_square_area[0] = max(largest_square_area[0], sub_problem_sol) dp_array[row][col] = sub_problem_sol return sub_problem_sol else: @@ -121,7 +125,9 @@ def update_area_of_max_square_using_dp_array(row: int, col: int, dp_array: List[ return largest_square_area[0] -def largest_square_area_in_matrix_bottom_up(rows: int, cols: int, mat: List[List[int]]) -> int: +def largest_square_area_in_matrix_bottom_up( + rows: int, cols: int, mat: list[list[int]] +) -> int: """ Function updates the largest_square_area, using bottom up approch. @@ -131,10 +137,10 @@ def largest_square_area_in_matrix_bottom_up(rows: int, cols: int, mat: List[List 0 """ - dp_array = [[0] * (cols + 1) for _ in range(rows+1)] + dp_array = [[0] * (cols + 1) for _ in range(rows + 1)] largest_square_area = 0 - for row in range(rows-1, -1, -1): - for col in range(cols-1, -1, -1): + for row in range(rows - 1, -1, -1): + for col in range(cols - 1, -1, -1): right = dp_array[row][col + 1] diagonal = dp_array[row + 1][col + 1] @@ -142,15 +148,16 @@ def largest_square_area_in_matrix_bottom_up(rows: int, cols: int, mat: List[List if mat[row][col] == 1: dp_array[row][col] = 1 + min(right, diagonal, bottom) - largest_square_area = max(dp_array[row][col], - largest_square_area) + largest_square_area = max(dp_array[row][col], largest_square_area) else: dp_array[row][col] = 0 return largest_square_area -def largest_square_area_in_matrix_bottom_up_space_optimization(rows: int, cols: int, mat: List[List[int]]) -> int: +def largest_square_area_in_matrix_bottom_up_space_optimization( + rows: int, cols: int, mat: list[list[int]] +) -> int: """ Function updates the largest_square_area, using bottom up approch. with space optimization. @@ -162,8 +169,8 @@ def largest_square_area_in_matrix_bottom_up_space_optimization(rows: int, cols: current_row = [0] * (cols + 1) next_row = [0] * (cols + 1) largest_square_area = 0 - for row in range(rows-1, -1, -1): - for col in range(cols-1, -1, -1): + for row in range(rows - 1, -1, -1): + for col in range(cols - 1, -1, -1): right = current_row[col + 1] diagonal = next_row[col + 1] @@ -171,8 +178,7 @@ def largest_square_area_in_matrix_bottom_up_space_optimization(rows: int, cols: if mat[row][col] == 1: current_row[col] = 1 + min(right, diagonal, bottom) - largest_square_area = max( - current_row[col], largest_square_area) + largest_square_area = max(current_row[col], largest_square_area) else: current_row[col] = 0 next_row = current_row From f3458d639afce7a4d23ab44bfc6efff27aa90b01 Mon Sep 17 00:00:00 2001 From: Shubham Kondekar <40213815+kondekarshubham123@users.noreply.github.com> Date: Wed, 26 Oct 2022 20:17:59 +0530 Subject: [PATCH 3/6] Update matrix/largest_square_area_in_matrix.py Co-authored-by: Caeden Perelli-Harris --- matrix/largest_square_area_in_matrix.py | 1 - 1 file changed, 1 deletion(-) diff --git a/matrix/largest_square_area_in_matrix.py b/matrix/largest_square_area_in_matrix.py index 3b27928c28d9..9055ae307bb1 100644 --- a/matrix/largest_square_area_in_matrix.py +++ b/matrix/largest_square_area_in_matrix.py @@ -43,7 +43,6 @@ """ -from typing import List def largest_square_area_in_matrix_top_down_approch( From 3a45fb71c0dbed1ff9e3cf1b64bde19a473afc33 Mon Sep 17 00:00:00 2001 From: Shubham Kondekar <40213815+kondekarshubham123@users.noreply.github.com> Date: Wed, 26 Oct 2022 20:18:17 +0530 Subject: [PATCH 4/6] Update matrix/largest_square_area_in_matrix.py Co-authored-by: Caeden Perelli-Harris --- matrix/largest_square_area_in_matrix.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix/largest_square_area_in_matrix.py b/matrix/largest_square_area_in_matrix.py index 9055ae307bb1..acd6c8cadf8e 100644 --- a/matrix/largest_square_area_in_matrix.py +++ b/matrix/largest_square_area_in_matrix.py @@ -189,4 +189,4 @@ def largest_square_area_in_matrix_bottom_up_space_optimization( import doctest doctest.testmod() - # print(largest_square_area_in_matrix_bottom_up(2, 2, [[1,1], [1,1]])) + print(largest_square_area_in_matrix_bottom_up(2, 2, [[1,1], [1,1]])) From 25f97afb14547caac3f19af93374e94e4eed6018 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 26 Oct 2022 14:51:41 +0000 Subject: [PATCH 5/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- matrix/largest_square_area_in_matrix.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/matrix/largest_square_area_in_matrix.py b/matrix/largest_square_area_in_matrix.py index acd6c8cadf8e..ae7cf681d63c 100644 --- a/matrix/largest_square_area_in_matrix.py +++ b/matrix/largest_square_area_in_matrix.py @@ -43,8 +43,6 @@ """ - - def largest_square_area_in_matrix_top_down_approch( rows: int, cols: int, mat: list[list[int]] ) -> int: @@ -189,4 +187,4 @@ def largest_square_area_in_matrix_bottom_up_space_optimization( import doctest doctest.testmod() - print(largest_square_area_in_matrix_bottom_up(2, 2, [[1,1], [1,1]])) + print(largest_square_area_in_matrix_bottom_up(2, 2, [[1, 1], [1, 1]])) From f1ff187c42492ed962cef8a9bb0a4cc3f726b571 Mon Sep 17 00:00:00 2001 From: Shubham Kondekar <40213815+kondekarshubham123@users.noreply.github.com> Date: Wed, 26 Oct 2022 20:33:13 +0530 Subject: [PATCH 6/6] Update largest_square_area_in_matrix.py --- matrix/largest_square_area_in_matrix.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/matrix/largest_square_area_in_matrix.py b/matrix/largest_square_area_in_matrix.py index ae7cf681d63c..cf975cb7ce1f 100644 --- a/matrix/largest_square_area_in_matrix.py +++ b/matrix/largest_square_area_in_matrix.py @@ -14,7 +14,7 @@ Output: 2 -Explaination: The maximum size of the square +Explanation: The maximum size of the square sub-matrix is 2. The matrix itself is the maximum sized sub-matrix in this case. --- @@ -26,10 +26,10 @@ [0, 0]] Output: 0 -Explaination: There is no 1 in the matrix. +Explanation: There is no 1 in the matrix. -Approch: +Approach: We initialize another matrix (dp) with the same dimensions as the original one initialized with all 0’s. @@ -50,7 +50,7 @@ def largest_square_area_in_matrix_top_down_approch( Function updates the largest_square_area[0], if recursive call found square with maximum area. - We arent using dp_array here, so the time complexity would be exponential. + We aren't using dp_array here, so the time complexity would be exponential. >>> largest_square_area_in_matrix_top_down_approch(2, 2, [[1,1], [1,1]]) 2 @@ -126,7 +126,7 @@ def largest_square_area_in_matrix_bottom_up( rows: int, cols: int, mat: list[list[int]] ) -> int: """ - Function updates the largest_square_area, using bottom up approch. + Function updates the largest_square_area, using bottom up approach. >>> largest_square_area_in_matrix_bottom_up(2, 2, [[1,1], [1,1]]) 2 @@ -156,7 +156,8 @@ def largest_square_area_in_matrix_bottom_up_space_optimization( rows: int, cols: int, mat: list[list[int]] ) -> int: """ - Function updates the largest_square_area, using bottom up approch. with space optimization. + Function updates the largest_square_area, using bottom up + approach. with space optimization. >>> largest_square_area_in_matrix_bottom_up_space_optimization(2, 2, [[1,1], [1,1]]) 2