diff --git a/Dynamic Programming/Maximal Rectangle/README.md b/Dynamic Programming/Maximal Rectangle/README.md new file mode 100644 index 00000000..5dbe47b5 --- /dev/null +++ b/Dynamic Programming/Maximal Rectangle/README.md @@ -0,0 +1,54 @@ +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. + + + + + + diff --git a/Dynamic Programming/Maximal Rectangle/program.c b/Dynamic Programming/Maximal Rectangle/program.c new file mode 100644 index 00000000..ea377d5f --- /dev/null +++ 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; +} diff --git a/Dynamic Programming/Minimum Cost to Cut a Stick/program.c b/Dynamic Programming/Minimum Cost to Cut a Stick/program.c deleted file mode 100644 index 8fd8d8eb..00000000 --- a/Dynamic Programming/Minimum Cost to Cut a Stick/program.c +++ /dev/null @@ -1,50 +0,0 @@ -#include -#include -#include - -// Comparison function for qsort (used to sort the cuts array) -int compare(const void *a, const void *b) { - return (*(int*)a - *(int*)b); -} - -int minCost(int n, int* cuts, int cutsSize) { - int* c = (int*)malloc((cutsSize + 2) * sizeof(int)); - for (int i = 0; i < cutsSize; i++) { - c[i + 1] = cuts[i]; - } - c[0] = 0; - c[cutsSize + 1] = n; - qsort(c, cutsSize + 2, sizeof(int), compare); - - int dp[cutsSize + 2][cutsSize + 2]; - for (int i = 0; i < cutsSize + 2; i++) { - for (int j = 0; j < cutsSize + 2; j++) { - dp[i][j] = 0; - } - } - - for (int i = 2; i < cutsSize + 2; i++) { - for (int j = i - 2; j >= 0; j--) { - dp[j][i] = INT_MAX; - for (int k = j + 1; k < i; k++) { - int cost = c[i] - c[j] + dp[j][k] + dp[k][i]; - if (cost < dp[j][i]) { - dp[j][i] = cost; - } - } - } - } - - int result = dp[0][cutsSize + 1]; - free(c); - return result; -} - -int main() { - int cuts[] = {1, 3, 4, 5}; - int n = 7; - int cutsSize = sizeof(cuts) / sizeof(cuts[0]); - int result = minCost(n, cuts, cutsSize); - printf("Minimum cost to cut the stick is %d\n", result); - return 0; -} diff --git a/Dynamic Programming/Minimum Cost to Cut a Stick/readme b/Dynamic Programming/Minimum Cost to Cut a Stick/readme deleted file mode 100644 index 368ac9ac..00000000 --- a/Dynamic Programming/Minimum Cost to Cut a Stick/readme +++ /dev/null @@ -1,64 +0,0 @@ -# Minimum Cost to Cut a Stick - -This project is an implementation of an algorithm to calculate the minimum cost required to cut a stick into specified pieces. The goal is to determine the optimal sequence of cuts that minimizes the total cost. - -## Problem Description - -Given a stick of length `n` and an array of integers `cuts`, where each integer represents a position on the stick where a cut can be made, the objective is to minimize the total cost of making the cuts. The cost of each cut is the length of the stick being cut at that step. The task is to compute the minimum cost to perform all cuts. - -### Example - -For a stick of length `n = 7` and cuts at positions `[1, 3, 4, 5]`, the minimum cost to cut the stick is computed by choosing the sequence of cuts that result in the lowest possible total cost. - -## Approach - -This solution uses dynamic programming to solve the problem efficiently. - -1. **Sorting the Cuts**: The positions of the cuts are sorted to determine the order of making cuts from the smallest to the largest position. - -2. **Dynamic Programming Table**: A 2D DP table (`dp`) is created, where `dp[i][j]` represents the minimum cost to cut the stick between positions `i` and `j`. - -3. **Iterative Solution**: Using a nested loop structure, the algorithm iteratively fills the DP table with minimum costs by checking possible partitions (cuts) between each sub-stick segment. - -4. **Result Extraction**: The final result, the minimum cost to cut the stick, is stored in `dp[0][cutsSize + 1]`, which represents the cost to cut the stick from the start to the end position. - -## Code Explanation - -The core code is implemented in C. Here is an overview of the key components: - -### 1. `compare` Function -A helper function used to sort the `cuts` array for correct order of cuts. - -### 2. `minCost` Function -This function calculates the minimum cost to cut the stick using dynamic programming. - -- **Parameters**: - - `n`: Length of the stick. - - `cuts`: Array of positions where cuts are needed. - - `cutsSize`: Number of cuts in the `cuts` array. - -- **Steps**: - 1. Initialize an array `c` to store sorted positions of cuts, including the start (0) and end (n) of the stick. - 2. Sort `c` for easier calculation. - 3. Define a 2D DP array and initialize all entries to zero. - 4. Iterate over possible sub-stick segments and compute the minimum cost for each segment using dynamic programming. - 5. Return the minimum cost from the `dp` array. - -### 3. `main` Function -The `main` function provides a test case to run the `minCost` function and displays the result. - -### Example Usage -The `main` function in this code provides an example usage of the `minCost` function, printing the minimum cost to cut the stick of length `7` with cuts at positions `[1, 3, 4, 5]`. - -### Input -The program can be modified to take different inputs for `n` and the `cuts` array. - -### Output -The output will display the minimum cost to make all cuts. - -## Installation - -1. Clone this repository. - ```bash - git clone https://github.com/yourusername/min-cost-stick-cutting.git - cd min-cost-stick-cutting diff --git a/Graph Algorithms/Swim in Rising Water/program.c b/Graph Algorithms/Swim in Rising Water/program.c deleted file mode 100644 index 756553db..00000000 --- a/Graph Algorithms/Swim in Rising Water/program.c +++ /dev/null @@ -1,99 +0,0 @@ -#include -#include -#include - -int **arr; -int n; -int dir[4][2] = {{0, 1}, {0, -1}, {-1, 0}, {1, 0}}; - -// Function to perform BFS traversal -bool helper(int x) { - if (arr[0][0] > x) return false; - - int **visited = (int **)malloc(n * sizeof(int *)); - for (int i = 0; i < n; i++) { - visited[i] = (int *)calloc(n, sizeof(int)); - } - - int queue[n * n][2]; - int front = 0, rear = 0; - queue[rear][0] = 0; - queue[rear++][1] = 0; - visited[0][0] = 1; - - while (front < rear) { - int r = queue[front][0]; - int c = queue[front++][1]; - - if (r == n - 1 && c == n - 1) { - for (int i = 0; i < n; i++) { - free(visited[i]); - } - free(visited); - return true; - } - - for (int i = 0; i < 4; i++) { - int nr = r + dir[i][0]; - int nc = c + dir[i][1]; - if (nr >= 0 && nc >= 0 && nr < n && nc < n && visited[nr][nc] == 0 && arr[nr][nc] <= x) { - queue[rear][0] = nr; - queue[rear++][1] = nc; - visited[nr][nc] = 1; - } - } - } - - for (int i = 0; i < n; i++) { - free(visited[i]); - } - free(visited); - - return false; -} - -// Main function to solve the swim in water problem -int swimInWater(int **grid, int gridSize) { - arr = grid; - n = gridSize; - int st = 0, end = 2505, ans = -1; - - while (st <= end) { - int mid = st + (end - st) / 2; - if (helper(mid)) { - ans = mid; - end = mid - 1; - } else { - st = mid + 1; - } - } - return ans; -} - -// Main function -int main() { - printf("Enter the grid size (n x n): "); - scanf("%d", &n); - - arr = (int **)malloc(n * sizeof(int *)); - for (int i = 0; i < n; i++) { - arr[i] = (int *)malloc(n * sizeof(int)); - } - - printf("Enter the grid elements:\n"); - for (int i = 0; i < n; i++) { - for (int j = 0; j < n; j++) { - scanf("%d", &arr[i][j]); - } - } - - int result = swimInWater(arr, n); - printf("Minimum time to swim to the bottom-right corner: %d\n", result); - - for (int i = 0; i < n; i++) { - free(arr[i]); - } - free(arr); - - return 0; -}