Dada una array 2D, encuentre la subarray rectangular más grande cuya suma sea 0. Por ejemplo, considere la siguiente array de entrada N x M
Ejemplos:
Input : 1, 2, 3 -3, -2, -1 1, 7, 5 Output : 1, 2, 3 -3, -2, -1 Input : 9, 7, 16, 5 1, -6, -7, 3 1, 8, 7, 9 7, -2, 0, 10 Output :-6, -7 8, 7 -2, 0
La solución ingenua para este problema es verificar todos los rectángulos posibles en una array 2D dada. Esta solución requiere 4 bucles anidados y la complejidad de tiempo de esta solución sería O(n^4).
La solución se basa en el rectángulo de suma máxima en una array 2D . La idea es reducir el problema a una array de 1 D. Podemos usar Hashing para encontrar la longitud máxima del subarreglo en un arreglo 1-D en tiempo O(n). Arreglamos las columnas izquierda y derecha una por una y encontramos el subarreglo más grande con filas contiguas de suma 0 para cada par de columnas izquierda y derecha. Básicamente, encontramos números de fila superior e inferior (cuya suma es cero) para cada par fijo de columnas izquierda y derecha.
Para encontrar los números de las filas superior e inferior, calcule la suma de los elementos en cada fila de izquierda a derecha y almacene estas sumas en una array, digamos temp[]. Entonces temp[i] indica la suma de los elementos de izquierda a derecha en la fila i. Si encontramos el subarreglo más grande con 0 sum en temp, y no. de elementos es mayor que el anterior no. de elementos, luego actualice los valores de final row_up, final row_down, final col_left, final col_right.
Implementación:
CPP
// A C++ program to find Largest rectangular // sub-matrix whose sum is 0 #include <bits/stdc++.h> using namespace std; const int MAX = 100; // This function basically finds largest 0 // sum subarray in temp[0..n-1]. If 0 sum // does't exist, then it returns false. Else // it returns true and sets starting and // ending indexes as starti and endj. bool sumZero(int temp[], int* starti, int* endj, int n) { // Map to store the previous sums map<int, int> presum; int sum = 0; // Initialize sum of elements // Initialize length of sub-array with sum 0 int max_length = 0; // Traverse through the given array for (int i = 0; i < n; i++) { // Add current element to sum sum += temp[i]; if (temp[i] == 0 && max_length == 0) { *starti = i; *endj = i; max_length = 1; } if (sum == 0) { if (max_length < i + 1) { *starti = 0; *endj = i; } max_length = i + 1; } // Look for this sum in Hash table if (presum.find(sum) != presum.end()) { // store previous max_length so // that we can check max_length // is updated or not int old = max_length; // If this sum is seen before, // then update max_len max_length = max(max_length, i - presum[sum]); if (old < max_length) { // If max_length is updated then // enter and update start and end // point of array *endj = i; *starti = presum[sum] + 1; } } else // Else insert this sum with // index in hash table presum[sum] = i; } // Return true if max_length is non-zero return (max_length != 0); } // The main function that finds Largest rectangle // sub-matrix in a[][] whose sum is 0. void sumZeroMatrix(int a[][MAX], int row, int col) { int temp[row]; // Variables to store the final output int fup = 0, fdown = 0, fleft = 0, fright = 0; int sum; int up, down; int maxl = INT_MIN; // Set the left column for (int left = 0; left < col; left++) { // Initialize all elements of temp as 0 memset(temp, 0, sizeof(temp)); // Set the right column for the left column // set by outer loop for (int right = left; right < col; right++) { // Calculate sum between current left // and right for every row 'i' for (int i = 0; i < row; i++) temp[i] += a[i][right]; // Find largest subarray with 0 sum in // temp[]. The sumZero() function also // sets values of start and finish. So // 'sum' is sum of rectangle between (start, // left) and (finish, right) which is // boundary columns strictly as left and right. bool sum = sumZero(temp, &up, &down, row); int ele = (down - up + 1) * (right - left + 1); // Compare no. of elements with previous // no. of elements in sub-Matrix. // If new sub-matrix has more elements // then update maxl and final boundaries // like fup, fdown, fleft, fright if (sum && ele > maxl) { fup = up; fdown = down; fleft = left; fright = right; maxl = ele; } } } // If there is no change in boundaries // than check if a[0][0] is 0 // If it not zero then print // that no such zero-sum sub-matrix exists if (fup == 0 && fdown == 0 && fleft == 0 && fright == 0 && a[0][0] != 0) { cout << "No zero-sum sub-matrix exists"; return; } // Print final values for (int j = fup; j <= fdown; j++) { for (int i = fleft; i <= fright; i++) cout << a[j][i] << " "; cout << endl; } } // Driver program to test above functions int main() { int a[][MAX] = { { 9, 7, 16, 5 }, { 1, -6, -7, 3 }, { 1, 8, 7, 9 }, { 7, -2, 0, 10 } }; int row = 4, col = 4; sumZeroMatrix(a, row, col); return 0; }
-6 -7 8 7 -2 0
Este artículo es una contribución de Harshit Agrawal . Si te gusta GeeksforGeeks y te gustaría contribuir, también puedes escribir un artículo usando write.geeksforgeeks.org o enviar tu artículo por correo a review-team@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks.
Publicación traducida automáticamente
Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA