From ac426995120e190a9ee10567ffed6410f403a965 Mon Sep 17 00:00:00 2001 From: Anany Dev Date: Mon, 4 Nov 2024 19:31:55 +0530 Subject: [PATCH 1/5] maximalRectangle --- .../maximal rectangle/README.md | 48 +++++++++++++++++++ .../maximal rectangle/program.c | 0 2 files changed, 48 insertions(+) create mode 100644 Dynamic Programming/maximal rectangle/README.md create mode 100644 Dynamic Programming/maximal rectangle/program.c diff --git a/Dynamic Programming/maximal rectangle/README.md b/Dynamic Programming/maximal rectangle/README.md new file mode 100644 index 00000000..a7e29f3e --- /dev/null +++ b/Dynamic Programming/maximal rectangle/README.md @@ -0,0 +1,48 @@ +Problem Overview +The task is to find the largest rectangle containing only 1's in a given binary matrix. Each element in the matrix is either '0' or '1', and we want to calculate the maximum area of contiguous '1's that can form a rectangle. + +Approach +The problem can be approached using the concept of dynamic histogram heights, where each row of the matrix is treated as a base and we calculate the histogram height of each column based on the presence of '1's in the rows above it. This allows us to use techniques similar to finding the largest rectangle in a histogram for each row, which can be efficiently solved with the following steps. + +Steps to Solve +Initialize Arrays: + +heights[]: Stores the height of '1's for each column. At any row i, if matrix[i][j] is '1', the height at heights[j] is incremented; otherwise, it's reset to 0. +leftBoundaries[]: Tracks the left boundary (leftmost column where '1's can extend) for each column in the current row. +rightBoundaries[]: Tracks the right boundary (rightmost column where '1's can extend) for each column in the current row. +Row-by-Row Processing: + +For each row, update the heights[], leftBoundaries[], and rightBoundaries[] arrays. +Calculate the maximum area for each rectangle ending at each column by multiplying the height by the width defined by the difference between the right and left boundaries. +Calculate Maximum Rectangle Area: + +For each column, calculate the rectangle area using the formula area = height * (rightBoundary - leftBoundary). +Update maxRectangle with the maximum area encountered. +Helper Functions +updateHeightsAndLeftBoundaries: Updates the heights[] array and leftBoundaries[] for the current row. If matrix[i][j] is '1', heights[j] is incremented, and leftBoundaries[j] is updated based on the current left boundary. Otherwise, heights[j] is reset to 0, and the left boundary is updated. + +updateRightBoundaries: Updates the rightBoundaries[] array for the current row. If matrix[i][j] is '1', rightBoundaries[j] is updated based on the current right boundary. If not, rightBoundaries[j] is reset, and right is adjusted. + +calculateMaxRectangle: Iterates over each column and calculates the area for each possible rectangle using heights, leftBoundaries, and rightBoundaries. It then updates maxRectangle if a larger area is found. + +Complexity Analysis +Time Complexity: +š‘‚ +( +š‘š +Ɨ +š‘› +) +O(mƗn), where +š‘š +m is the number of rows and +š‘› +n is the number of columns. Each cell is processed once, and boundary updates are linear. +Space Complexity: +š‘‚ +( +š‘› +) +O(n), for storing heights, leftBoundaries, and rightBoundaries. +Summary +This approach leverages a dynamic programming technique to keep track of heights and boundaries, transforming the problem into a maximal rectangle calculation on each row as if it were a histogram. By iteratively updating the boundaries and heights, we efficiently compute the maximal rectangle area in a binary matrix. This method ensures that the solution is optimal for large matrices while maintaining manageable space complexity. \ No newline at end of file diff --git a/Dynamic Programming/maximal rectangle/program.c b/Dynamic Programming/maximal rectangle/program.c new file mode 100644 index 00000000..e69de29b From 3bd97ff69f037128ba2c8b526a4c3c5952ba3a92 Mon Sep 17 00:00:00 2001 From: Anany Dev Date: Fri, 8 Nov 2024 17:02:58 +0530 Subject: [PATCH 2/5] Climbing stairs --- Dynamic Programming/Climbing stairs/README.md | 31 +++++++++++++++++++ Dynamic Programming/Climbing stairs/program.c | 18 +++++++++++ 2 files changed, 49 insertions(+) create mode 100644 Dynamic Programming/Climbing stairs/README.md create mode 100644 Dynamic Programming/Climbing stairs/program.c diff --git a/Dynamic Programming/Climbing stairs/README.md b/Dynamic Programming/Climbing stairs/README.md new file mode 100644 index 00000000..5fc8bcfd --- /dev/null +++ b/Dynamic Programming/Climbing stairs/README.md @@ -0,0 +1,31 @@ +Climbing Stairs Problem +This problem is based on a classic dynamic programming challenge where you have to calculate the number of distinct ways to reach the top of a staircase with n steps, given that you can climb either 1 or 2 steps at a time. + +Problem Explanation +The problem is a simple application of combinatorial logic. At each step, there are two choices: + +Take a single step. +Take two steps. +We can break down the solution as follows: + +If we are on the n-th step, there are two possibilities for reaching it: +We arrived from the (n-1)-th step by taking a single step. +We arrived from the (n-2)-th step by taking two steps. +This logic forms a recurrence relation: dp[š‘›]=dp[š‘›āˆ’1]+dp[š‘›āˆ’2] +dp[n]=dp[nāˆ’1]+dp[nāˆ’2] + +Here, dp[i] represents the number of ways to reach the i-th step. + +Solution Approach +Dynamic Programming Array: We initialize an array dp where dp[i] will store the number of ways to reach the i-th step. +Base Cases: +dp[0] = 1: There is 1 way to stay at the ground (by doing nothing). +dp[1] = 1: There is only one way to reach the first step (a single step). +Iterative Calculation: +Starting from i = 2 up to i = n, we compute dp[i] based on the relation dp[i] = dp[i-1] + dp[i-2]. +This ensures that each step is built upon the previous ones, leveraging previously computed values to avoid redundant calculations. +Time Complexity +The solution runs in O(n) time, as each step from 2 to n is computed once in a linear scan. + +Space Complexity +The space complexity is O(n) due to the storage required for the dp array, which holds the number of ways to reach each step up to n. \ No newline at end of file diff --git a/Dynamic Programming/Climbing stairs/program.c b/Dynamic Programming/Climbing stairs/program.c new file mode 100644 index 00000000..dc278549 --- /dev/null +++ b/Dynamic Programming/Climbing stairs/program.c @@ -0,0 +1,18 @@ +class Solution { + public int climbStairs(int n) + { + if (n == 0 || n == 1) + { + return 1; + } + + int[] dp = new int[n+1]; + dp[0] = dp[1] = 1; + + for (int i = 2; i <= n; i++) + { + dp[i] = dp[i-1] + dp[i-2]; + } + return dp[n]; + } +} \ No newline at end of file From a977fc113846ee8a55c092259d9e27be23a80bf0 Mon Sep 17 00:00:00 2001 From: Anany Dev Date: Fri, 8 Nov 2024 17:14:39 +0530 Subject: [PATCH 3/5] CLIMBING STAIRS --- Dynamic Programming/Climbing stairs/README.md | 59 ++++++++------- .../maximal rectangle/program.c | 71 +++++++++++++++++++ 2 files changed, 105 insertions(+), 25 deletions(-) diff --git a/Dynamic Programming/Climbing stairs/README.md b/Dynamic Programming/Climbing stairs/README.md index 5fc8bcfd..b6248e4f 100644 --- a/Dynamic Programming/Climbing stairs/README.md +++ b/Dynamic Programming/Climbing stairs/README.md @@ -1,31 +1,40 @@ Climbing Stairs Problem -This problem is based on a classic dynamic programming challenge where you have to calculate the number of distinct ways to reach the top of a staircase with n steps, given that you can climb either 1 or 2 steps at a time. +This program provides a solution to the "Climbing Stairs" problem, a classic example of dynamic programming. The problem can be stated as follows: -Problem Explanation -The problem is a simple application of combinatorial logic. At each step, there are two choices: +Problem Statement: +A person is at the bottom of a staircase with n steps and wants to reach the top. They can take either 1 or 2 steps at a time. The task is to determine the number of distinct ways the person can reach the top of the staircase. -Take a single step. -Take two steps. -We can break down the solution as follows: +Approach: +Dynamic Programming: -If we are on the n-th step, there are two possibilities for reaching it: -We arrived from the (n-1)-th step by taking a single step. -We arrived from the (n-2)-th step by taking two steps. -This logic forms a recurrence relation: dp[š‘›]=dp[š‘›āˆ’1]+dp[š‘›āˆ’2] -dp[n]=dp[nāˆ’1]+dp[nāˆ’2] +This problem has overlapping subproblems, making it a suitable candidate for dynamic programming. +Define dp[i] as the number of ways to reach the i-th step. +The number of ways to reach step i is the sum of ways to reach the previous step i-1 and the step before that, i-2. This is because the person can arrive at step i by taking a single step from i-1 or a double step from i-2. +Thus, the recurrence relation is: -Here, dp[i] represents the number of ways to reach the i-th step. - -Solution Approach -Dynamic Programming Array: We initialize an array dp where dp[i] will store the number of ways to reach the i-th step. +š‘‘š‘[š‘–]=š‘‘š‘[š‘–āˆ’1]+š‘‘š‘[š‘–āˆ’2]dp[i]=dp[iāˆ’1]+dp[iāˆ’2] Base Cases: -dp[0] = 1: There is 1 way to stay at the ground (by doing nothing). -dp[1] = 1: There is only one way to reach the first step (a single step). -Iterative Calculation: -Starting from i = 2 up to i = n, we compute dp[i] based on the relation dp[i] = dp[i-1] + dp[i-2]. -This ensures that each step is built upon the previous ones, leveraging previously computed values to avoid redundant calculations. -Time Complexity -The solution runs in O(n) time, as each step from 2 to n is computed once in a linear scan. - -Space Complexity -The space complexity is O(n) due to the storage required for the dp array, which holds the number of ways to reach each step up to n. \ No newline at end of file + +If there are no steps (n = 0), there is 1 way (doing nothing). +If there is one step (n = 1), there is also 1 way to reach it. +Building the Solution: + +Create an array dp of size n+1 to store the number of ways to reach each step up to n. +Initialize dp[0] = 1 and dp[1] = 1 as per the base cases. +Use a loop to fill the array from dp[2] up to dp[n] using the recurrence relation. +Finally, dp[n] will contain the number of distinct ways to reach the top of the staircase with n steps. +Example: +For n = 5, the program calculates the ways as follows: + +dp[0] = 1 +dp[1] = 1 +dp[2] = dp[1] + dp[0] = 2 +dp[3] = dp[2] + dp[1] = 3 +dp[4] = dp[3] + dp[2] = 5 +dp[5] = dp[4] + dp[3] = 8 +So, there are 8 distinct ways to reach the 5th step. + +Complexity Analysis: +Time Complexity: O(n) because we only need to compute each value in dp from 0 to n. +Space Complexity: O(n) for storing the dp array. +This dynamic programming approach efficiently computes the number of ways to climb the staircase, demonstrating how overlapping subproblems and optimal substructure can be leveraged to solve problems effectively. \ No newline at end of file diff --git a/Dynamic Programming/maximal rectangle/program.c b/Dynamic Programming/maximal rectangle/program.c index e69de29b..a80dc100 100644 --- a/Dynamic Programming/maximal rectangle/program.c +++ b/Dynamic Programming/maximal rectangle/program.c @@ -0,0 +1,71 @@ +#include +#include +#include + +int maximalRectangle(char** matrix, int matrixSize, int* matrixColSize) { + if (matrix == NULL || matrixSize == 0 || matrixColSize[0] == 0) { + return 0; + } + + int m = matrixSize; + int n = matrixColSize[0]; + + int* heights = (int*)calloc(n, sizeof(int)); + int* leftBoundaries = (int*)calloc(n, sizeof(int)); + int* rightBoundaries = (int*)malloc(n * sizeof(int)); + for (int i = 0; i < n; i++) { + rightBoundaries[i] = n; + } + + int maxRectangle = 0; + + for (int i = 0; i < m; i++) { + int left = 0; + int right = n; + + updateHeightsAndLeftBoundaries(matrix[i], heights, leftBoundaries, n, &left); + + updateRightBoundaries(matrix[i], rightBoundaries, n, &right); + + maxRectangle = calculateMaxRectangle(heights, leftBoundaries, rightBoundaries, n, maxRectangle); + } + + free(heights); + free(leftBoundaries); + free(rightBoundaries); + + return maxRectangle; +} + +void updateHeightsAndLeftBoundaries(char* row, int* heights, int* leftBoundaries, int n, int* left) { + for (int j = 0; j < n; j++) { + if (row[j] == '1') { + heights[j]++; + leftBoundaries[j] = leftBoundaries[j] > *left ? leftBoundaries[j] : *left; + } else { + heights[j] = 0; + leftBoundaries[j] = 0; + *left = j + 1; + } + } +} + +void updateRightBoundaries(char* row, int* rightBoundaries, int n, int* right) { + for (int j = n - 1; j >= 0; j--) { + if (row[j] == '1') { + rightBoundaries[j] = rightBoundaries[j] < *right ? rightBoundaries[j] : *right; + } else { + rightBoundaries[j] = n; + *right = j; + } + } +} + +int calculateMaxRectangle(int* heights, int* leftBoundaries, int* rightBoundaries, int n, int maxRectangle) { + for (int j = 0; j < n; j++) { + int width = rightBoundaries[j] - leftBoundaries[j]; + int area = heights[j] * width; + maxRectangle = maxRectangle > area ? maxRectangle : area; + } + return maxRectangle; +} \ No newline at end of file From afca29ecb554b02a9574aa9d19e399000a319962 Mon Sep 17 00:00:00 2001 From: Pankaj Kumar Bind <73558583+pankaj-bind@users.noreply.github.com> Date: Sat, 9 Nov 2024 00:15:52 +0530 Subject: [PATCH 4/5] Delete Dynamic Programming/maximal rectangle/README.md --- .../maximal rectangle/README.md | 48 ------------------- 1 file changed, 48 deletions(-) delete mode 100644 Dynamic Programming/maximal rectangle/README.md diff --git a/Dynamic Programming/maximal rectangle/README.md b/Dynamic Programming/maximal rectangle/README.md deleted file mode 100644 index a7e29f3e..00000000 --- a/Dynamic Programming/maximal rectangle/README.md +++ /dev/null @@ -1,48 +0,0 @@ -Problem Overview -The task is to find the largest rectangle containing only 1's in a given binary matrix. Each element in the matrix is either '0' or '1', and we want to calculate the maximum area of contiguous '1's that can form a rectangle. - -Approach -The problem can be approached using the concept of dynamic histogram heights, where each row of the matrix is treated as a base and we calculate the histogram height of each column based on the presence of '1's in the rows above it. This allows us to use techniques similar to finding the largest rectangle in a histogram for each row, which can be efficiently solved with the following steps. - -Steps to Solve -Initialize Arrays: - -heights[]: Stores the height of '1's for each column. At any row i, if matrix[i][j] is '1', the height at heights[j] is incremented; otherwise, it's reset to 0. -leftBoundaries[]: Tracks the left boundary (leftmost column where '1's can extend) for each column in the current row. -rightBoundaries[]: Tracks the right boundary (rightmost column where '1's can extend) for each column in the current row. -Row-by-Row Processing: - -For each row, update the heights[], leftBoundaries[], and rightBoundaries[] arrays. -Calculate the maximum area for each rectangle ending at each column by multiplying the height by the width defined by the difference between the right and left boundaries. -Calculate Maximum Rectangle Area: - -For each column, calculate the rectangle area using the formula area = height * (rightBoundary - leftBoundary). -Update maxRectangle with the maximum area encountered. -Helper Functions -updateHeightsAndLeftBoundaries: Updates the heights[] array and leftBoundaries[] for the current row. If matrix[i][j] is '1', heights[j] is incremented, and leftBoundaries[j] is updated based on the current left boundary. Otherwise, heights[j] is reset to 0, and the left boundary is updated. - -updateRightBoundaries: Updates the rightBoundaries[] array for the current row. If matrix[i][j] is '1', rightBoundaries[j] is updated based on the current right boundary. If not, rightBoundaries[j] is reset, and right is adjusted. - -calculateMaxRectangle: Iterates over each column and calculates the area for each possible rectangle using heights, leftBoundaries, and rightBoundaries. It then updates maxRectangle if a larger area is found. - -Complexity Analysis -Time Complexity: -š‘‚ -( -š‘š -Ɨ -š‘› -) -O(mƗn), where -š‘š -m is the number of rows and -š‘› -n is the number of columns. Each cell is processed once, and boundary updates are linear. -Space Complexity: -š‘‚ -( -š‘› -) -O(n), for storing heights, leftBoundaries, and rightBoundaries. -Summary -This approach leverages a dynamic programming technique to keep track of heights and boundaries, transforming the problem into a maximal rectangle calculation on each row as if it were a histogram. By iteratively updating the boundaries and heights, we efficiently compute the maximal rectangle area in a binary matrix. This method ensures that the solution is optimal for large matrices while maintaining manageable space complexity. \ No newline at end of file From e77a98f527ccfb7aaf1050ec7f1d9f420c2caa04 Mon Sep 17 00:00:00 2001 From: Pankaj Kumar Bind <73558583+pankaj-bind@users.noreply.github.com> Date: Sat, 9 Nov 2024 00:16:13 +0530 Subject: [PATCH 5/5] Delete Dynamic Programming/maximal rectangle/program.c --- .../maximal rectangle/program.c | 71 ------------------- 1 file changed, 71 deletions(-) delete mode 100644 Dynamic Programming/maximal rectangle/program.c diff --git a/Dynamic Programming/maximal rectangle/program.c b/Dynamic Programming/maximal rectangle/program.c deleted file mode 100644 index a80dc100..00000000 --- a/Dynamic Programming/maximal rectangle/program.c +++ /dev/null @@ -1,71 +0,0 @@ -#include -#include -#include - -int maximalRectangle(char** matrix, int matrixSize, int* matrixColSize) { - if (matrix == NULL || matrixSize == 0 || matrixColSize[0] == 0) { - return 0; - } - - int m = matrixSize; - int n = matrixColSize[0]; - - int* heights = (int*)calloc(n, sizeof(int)); - int* leftBoundaries = (int*)calloc(n, sizeof(int)); - int* rightBoundaries = (int*)malloc(n * sizeof(int)); - for (int i = 0; i < n; i++) { - rightBoundaries[i] = n; - } - - int maxRectangle = 0; - - for (int i = 0; i < m; i++) { - int left = 0; - int right = n; - - updateHeightsAndLeftBoundaries(matrix[i], heights, leftBoundaries, n, &left); - - updateRightBoundaries(matrix[i], rightBoundaries, n, &right); - - maxRectangle = calculateMaxRectangle(heights, leftBoundaries, rightBoundaries, n, maxRectangle); - } - - free(heights); - free(leftBoundaries); - free(rightBoundaries); - - return maxRectangle; -} - -void updateHeightsAndLeftBoundaries(char* row, int* heights, int* leftBoundaries, int n, int* left) { - for (int j = 0; j < n; j++) { - if (row[j] == '1') { - heights[j]++; - leftBoundaries[j] = leftBoundaries[j] > *left ? leftBoundaries[j] : *left; - } else { - heights[j] = 0; - leftBoundaries[j] = 0; - *left = j + 1; - } - } -} - -void updateRightBoundaries(char* row, int* rightBoundaries, int n, int* right) { - for (int j = n - 1; j >= 0; j--) { - if (row[j] == '1') { - rightBoundaries[j] = rightBoundaries[j] < *right ? rightBoundaries[j] : *right; - } else { - rightBoundaries[j] = n; - *right = j; - } - } -} - -int calculateMaxRectangle(int* heights, int* leftBoundaries, int* rightBoundaries, int n, int maxRectangle) { - for (int j = 0; j < n; j++) { - int width = rightBoundaries[j] - leftBoundaries[j]; - int area = heights[j] * width; - maxRectangle = maxRectangle > area ? maxRectangle : area; - } - return maxRectangle; -} \ No newline at end of file