Based on the “largest square in a histogram” problem (shown below), the goal is to analyze a binary 2D array consisting of ones and zeroes, and find the largest square section of the array that contains ones. This is useful for a number of tasks in statistics and image processing.

Largest rectangle in a histogram. (C) GeeksForGeeks.com – Shown under a FAIR USE exemption to the DMCA for works relating to public knowledge.
Using a “waterfall” incrementing operation, we arrive at the code shown below.
#include <stdio.h> #include <time.h> #include <stdlib.h> #define bool int #define R 20 #define C 20 void printMaxSubSquare(bool M[R][C]) { int i,j; int S[R][C]; int max_of_s, max_i, max_j; /* Set first column of S[][]*/ for(i = 0; i < R; i++) S[i][0] = M[i][0]; /* Set first row of S[][]*/ for(j = 0; j < C; j++) S[0][j] = M[0][j]; /* Construct other entries of S[][]*/ for(i = 1; i < R; i++) { for(j = 1; j < C; j++) { if(M[i][j] == 1) S[i][j] = min(S[i][j-1], S[i-1][j], S[i-1][j-1]) + 1; else S[i][j] = 0; } } /* Find the maximum entry, and indexes of maximum entry in S[][] */ max_of_s = S[0][0]; max_i = 0; max_j = 0; for(i = 0; i < R; i++) { for(j = 0; j < C; j++) { if(max_of_s < S[i][j]) { max_of_s = S[i][j]; max_i = i; max_j = j; } } } printf("max_of_s:%d - max_i:%d - max_j:%d\n", max_of_s, max_i, max_j); printf("\n Maximum size sub-matrix is: \n"); for(i = max_i; i > max_i - max_of_s; i--) { for(j = max_j; j > max_j - max_of_s; j--) { printf("%d ", M[i][j]); } printf("\n"); } /* Print a prettier description of our result */ for (i=0; i<R; i++) { for (j=0; j<C; j++) { if ((i > max_i - max_of_s) && (i <= max_i) && (j > max_j - max_of_s) && (j <= max_j)) { printf("# "); } else { printf(". "); } } printf("\n"); } printf("\n"); /* Print out the sum column */ for (i=0; i<R; i++) { for (j=0; j<C; j++) { printf("%d ", S[i][j]); } printf("\n"); } printf("\n"); } /* UTILITY FUNCTIONS */ /* Function to get minimum of three values */ int min(int a, int b, int c) { int m = a; if (m > b) m = b; if (m > c) m = c; return m; } /* Driver function to test above functions */ int main() { int i, j; const int bias = 2; /* Set to "2" for a 50/50 random chance; Higher bias * means a greater chance of the value being set to * true, and a larger sub-square being likely. */ bool M[R][C] = { 0 }; /* bool M[R][C] = {{0, 1, 1, 0, 1}, {1, 1, 0, 1, 0}, {0, 1, 1, 1, 0}, {1, 1, 1, 1, 0}, {1, 1, 1, 1, 1}, {0, 0, 0, 0, 0}}; */ srand(time(NULL)); for (i=0; i<R; i++) { for (j=0; j<C; j++) { M[i][j] = (rand() % bias)>=(bias-1)?0:1; } } /* print overall square */ for (i=0; i<R; i++) { for (j=0; j<C; j++) { printf("%d ", M[i][j]); } printf("\n"); } printf("\n"); printMaxSubSquare(M); //getchar(); }
The best part about this, is by manipulating the “bias” variable, we can control the average number of ones versus zeros in the array, allowing us to see a number of different potential outcomes. With an “even” bias (ie: 50%), we see that the largest sub-square is often quite small.
0 1 0 1 0 0 1 1 1 1 1 0 0 0 1 0 1 1 1 0 1 1 1 1 0 1 1 1 1 1 0 1 1 1 0 0 1 0 1 1 0 1 0 0 0 0 0 0 1 0 1 0 1 0 1 0 1 0 1 1 0 0 0 1 1 1 1 1 1 0 0 1 0 0 1 1 0 0 1 0 0 1 1 1 1 0 1 0 1 1 1 1 1 0 0 1 1 0 0 0 1 1 1 0 1 0 1 0 0 0 0 1 0 1 0 0 1 1 1 1 0 1 0 1 0 1 1 0 0 1 0 0 0 1 1 1 1 1 1 0 0 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 1 0 1 0 0 1 0 1 1 1 1 0 1 1 1 0 1 0 1 1 0 0 1 0 1 0 0 1 1 0 1 0 1 0 1 1 0 1 1 0 1 0 1 1 0 0 0 0 1 1 0 0 1 0 1 1 1 0 1 1 1 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 1 1 1 1 1 0 1 1 0 0 0 0 0 0 1 1 1 0 0 1 1 0 1 0 0 1 1 1 0 1 0 1 0 1 0 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 1 0 1 1 1 0 1 0 1 1 1 1 1 0 1 1 1 1 0 1 1 1 0 0 0 1 0 0 1 1 1 0 1 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 1 0 0 1 1 0 0 0 0 0 1 0 1 1 1 0 0 0 0 1 1 1 1 0 0 1 1 1 1 1 1 1 0 1 0 0 0 1 1 1 0 0 0 1 1 1 0 1 1 1 1 0 1 1 0 1 1 0 1 0 0 1 0 max_of_s:2 - max_i:1 - max_j:7 Maximum size sub-matrix is: 1 1 1 1 . . . . . . # # . . . . . . . . . . . . . . . . . . # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 0 1 0 1 0 0 1 1 1 1 1 0 0 0 1 0 1 1 1 0 1 1 1 1 0 1 1 2 2 2 0 1 1 1 0 0 1 0 1 1 0 1 0 0 0 0 0 0 1 0 1 0 1 0 1 0 1 0 1 2 0 0 0 1 1 1 1 1 1 0 0 1 0 0 1 1 0 0 1 0 0 1 1 1 2 0 1 0 1 1 1 1 1 0 0 1 1 0 0 0 1 1 2 0 1 0 1 0 0 0 0 1 0 1 0 0 1 1 1 1 0 1 0 1 0 1 1 0 0 1 0 0 0 1 1 1 1 2 2 0 0 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 1 0 1 0 0 1 0 1 1 1 1 0 1 1 1 0 1 0 1 1 0 0 1 0 1 0 0 1 2 0 1 0 1 0 1 1 0 1 1 0 1 0 1 1 0 0 0 0 1 1 0 0 1 0 1 2 1 0 1 1 1 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 1 1 1 2 2 0 1 1 0 0 0 0 0 0 1 1 1 0 0 1 1 0 1 0 0 1 1 2 0 1 0 1 0 1 0 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 1 0 1 1 1 0 1 0 1 1 1 1 1 0 1 1 1 1 0 1 2 1 0 0 0 1 0 0 1 2 2 0 1 0 0 0 0 0 0 0 1 2 1 0 0 1 1 0 0 0 0 0 1 0 0 1 1 0 0 0 0 0 1 0 1 1 2 0 0 0 0 1 1 1 1 0 0 1 1 1 1 1 1 1 0 1 0 0 0 1 1 1 0 0 0 1 1 1 0 1 2 2 2 0 1 1 0 1 1 0 1 0 0 1 0
While with a modified bias (80% in the case below) we get much larger sub-squares.
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 max_of_s:14 - max_i:19 - max_j:18 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # # # # # # # # # # # . . . . . . # # # # # # # # # # # # # # . . . . . . # # # # # # # # # # # # # # . . . . . . # # # # # # # # # # # # # # . . . . . . # # # # # # # # # # # # # # . . . . . . # # # # # # # # # # # # # # . . . . . . # # # # # # # # # # # # # # . . . . . . # # # # # # # # # # # # # # . . . . . . # # # # # # # # # # # # # # . . . . . . # # # # # # # # # # # # # # . . . . . . # # # # # # # # # # # # # # . . . . . . # # # # # # # # # # # # # # . . . . . . # # # # # # # # # # # # # # . . . . . . # # # # # # # # # # # # # # . 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 1 2 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 2 3 0 1 2 3 4 5 5 5 5 5 5 5 5 5 5 5 5 1 2 3 1 1 2 3 4 5 6 6 6 6 0 1 2 3 4 5 6 1 2 3 2 2 2 3 4 5 6 7 7 7 1 1 2 3 4 5 6 1 2 3 3 3 3 3 4 5 6 7 8 8 2 2 2 3 4 5 6 1 2 3 4 4 4 4 4 5 6 7 8 9 3 3 3 3 4 5 6 1 2 3 4 5 5 5 5 5 6 7 8 9 4 4 4 4 4 5 6 1 2 3 4 5 6 6 6 6 6 7 8 9 5 5 5 5 5 5 6 1 2 3 4 5 6 7 7 7 7 7 8 9 6 6 6 6 6 6 6 1 2 3 4 5 6 7 8 8 8 8 8 9 7 7 7 7 7 7 7 1 2 3 4 5 6 7 8 9 9 9 9 9 8 8 8 8 8 8 8 1 2 3 4 5 6 7 8 9 10 10 10 10 9 9 9 9 9 9 9 1 0 1 2 3 4 5 6 7 8 9 10 11 10 10 10 10 10 10 10 1 1 1 2 0 1 2 3 4 5 6 7 8 9 10 11 11 11 11 11 1 2 2 2 0 1 2 3 4 5 6 7 8 9 10 11 12 12 12 12 1 2 3 3 1 1 2 3 4 5 6 7 8 9 10 11 12 13 13 13 1 2 3 4 2 2 2 3 4 5 6 7 8 9 10 11 12 13 14 14