Largest Rectangle with Column Swaps

Last Updated : 11 Aug, 2026

Given a binary matrix mat[][] of size n x m, find the maximum area of a rectangle containing only 1s. You are allowed to swap any columns of the matrix any number of times before forming the rectangle. Return the maximum possible rectangle area.

Examples:

Input: mat[][] = [[0, 1, 0, 1, 0], [0, 1, 0, 1, 1], [1, 1, 0, 1, 0]]
Output: 6
Explanation: By rearranging columns, we can form a rectangle of 1s with area 6.
0 0 1 1 0
0 0 1 1 1
1 0 1 1 0

Input: mat[][] = [[0, 1, 0, 1, 0], [0, 1, 1, 1, 1], [1, 1, 1, 0, 1], [1, 1, 1, 1, 1]]
Output: 9

Try It Yourself
redirect icon

[Naive Approach] Sort Heights Row-wise - O(n * m * log m) Time and O(n * m) Space

The idea is to use an auxiliary matrix to store count of consecutive 1's in every column. Once we have these counts, we sort all rows of auxiliary matrix in non-increasing order of counts. Finally traverse the sorted rows to find the maximum area. 

Let us understand with the following example.

    0 1 0 1 0    
    0 2 0 2 1     
    1 3 0 3 0

Step 1: First of all, calculate no. of consecutive 1's in every column. An auxiliary array height[][] is used to store the counts of consecutive 1's.

    0 1 0 1 0
    0 2 0 2 1
    1 3 0 3 0

Step 2: Sort the rows in non-increasing fashion. After sorting step the matrix height[][] would be 

    1 1 0 0 0
    2 2 1 0 0
    3 3 1 0 0

The sorting is actually the swapping of columns so that the column with the highest possible rectangle is placed first, after that comes the column that allows the second highest rectangle and so on. So, in the example there are 2 columns that can form a rectangle of height 3. That makes an area of 3*2 = 6. If we try to make the rectangle wider the height drops to 1, because there are no columns left that allow a higher rectangle on the 3rd row.

Step 3: Traverse each row of height[][] and check for the max area. Since every row is sorted by count of 1's, current area can be calculated by multiplying column number with value in height[i][j].

C++
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int maxArea(vector<vector<int>>& mat) {
    int n = mat.size();
    int m = mat[0].size();

    vector<vector<int>> height(n, vector<int>(m, 0));

    // Build height matrix.
    for (int j = 0; j < m; j++) {
        height[0][j] = mat[0][j];

        for (int i = 1; i < n; i++) {
            if (mat[i][j] == 1) {
                height[i][j] = height[i - 1][j] + 1;
            }
        }
    }

    int ans = 0;

    for (int i = 0; i < n; i++) {
        vector<int> row = height[i];

        // Sort heights because columns can be rearranged.
        sort(row.rbegin(), row.rend());

        for (int j = 0; j < m; j++) {
            ans = max(ans, row[j] * (j + 1));
        }
    }

    return ans;
}

int main() {
    vector<vector<int>> mat = {
        {0, 1, 0, 1, 0},
        {0, 1, 0, 1, 1},
        {1, 1, 0, 1, 0}
    };
    cout << maxArea(mat) << endl;

    mat = {
        {0, 1, 0, 1, 0},
        {0, 1, 1, 1, 1},
        {1, 1, 1, 0, 1},
        {1, 1, 1, 1, 1}
    };
    cout << maxArea(mat) << endl;

    return 0;
}
Java
import java.util.Collections;
import java.util.Arrays;

class GFG {
    static int maxArea(int[][] mat) {
        int n = mat.length;
        int m = mat[0].length;

        int[][] height = new int[n][m];

        // Build height matrix.
        for (int j = 0; j < m; j++) {
            height[0][j] = mat[0][j];

            for (int i = 1; i < n; i++) {
                if (mat[i][j] == 1) {
                    height[i][j] = height[i - 1][j] + 1;
                }
            }
        }

        int ans = 0;

        for (int i = 0; i < n; i++) {
            Integer[] row = new Integer[m];

            for (int j = 0; j < m; j++) {
                row[j] = height[i][j];
            }

            // Sort heights because columns can be rearranged.
            Arrays.sort(row, Collections.reverseOrder());

            for (int j = 0; j < m; j++) {
                ans = Math.max(ans, row[j] * (j + 1));
            }
        }

        return ans;
    }

    public static void main(String[] args) {
        int[][] mat = {
            {0, 1, 0, 1, 0},
            {0, 1, 0, 1, 1},
            {1, 1, 0, 1, 0}
        };
        System.out.println(maxArea(mat));

        mat = new int[][] {
            {0, 1, 0, 1, 0},
            {0, 1, 1, 1, 1},
            {1, 1, 1, 0, 1},
            {1, 1, 1, 1, 1}
        };
        System.out.println(maxArea(mat));
    }
}
Python
def maxArea(mat):
    n = len(mat)
    m = len(mat[0])

    height = [[0] * m for _ in range(n)]

    # Build height matrix.
    for j in range(m):
        height[0][j] = mat[0][j]

        for i in range(1, n):
            if mat[i][j] == 1:
                height[i][j] = height[i - 1][j] + 1

    ans = 0

    for i in range(n):
        row = height[i][:]

        # Sort heights because columns can be rearranged.
        row.sort(reverse=True)

        for j in range(m):
            ans = max(ans, row[j] * (j + 1))

    return ans


if __name__ == "__main__":
    mat = [
        [0, 1, 0, 1, 0],
        [0, 1, 0, 1, 1],
        [1, 1, 0, 1, 0]
    ]
    print(maxArea(mat))

    mat = [
        [0, 1, 0, 1, 0],
        [0, 1, 1, 1, 1],
        [1, 1, 1, 0, 1],
        [1, 1, 1, 1, 1]
    ]
    print(maxArea(mat))
C#
using System;
using System.Linq;

class GFG {
    static int maxArea(int[,] mat) {
        int n = mat.GetLength(0);
        int m = mat.GetLength(1);

        int[,] height = new int[n, m];

        // Build height matrix.
        for (int j = 0; j < m; j++) {
            height[0, j] = mat[0, j];

            for (int i = 1; i < n; i++) {
                if (mat[i, j] == 1) {
                    height[i, j] = height[i - 1, j] + 1;
                }
            }
        }

        int ans = 0;

        for (int i = 0; i < n; i++) {
            int[] row = new int[m];

            for (int j = 0; j < m; j++) {
                row[j] = height[i, j];
            }

            // Sort heights because columns can be rearranged.
            Array.Sort(row);
            Array.Reverse(row);

            for (int j = 0; j < m; j++) {
                ans = Math.Max(ans, row[j] * (j + 1));
            }
        }

        return ans;
    }

    static void Main() {
        int[,] mat = {
            {0, 1, 0, 1, 0},
            {0, 1, 0, 1, 1},
            {1, 1, 0, 1, 0}
        };
        Console.WriteLine(maxArea(mat));

        mat = new int[,] {
            {0, 1, 0, 1, 0},
            {0, 1, 1, 1, 1},
            {1, 1, 1, 0, 1},
            {1, 1, 1, 1, 1}
        };
        Console.WriteLine(maxArea(mat));
    }
}
JavaScript
function maxArea(mat) {
    const n = mat.length;
    const m = mat[0].length;

    const height = Array.from({ length: n }, () => new Array(m).fill(0));

    // Build height matrix.
    for (let j = 0; j < m; j++) {
        height[0][j] = mat[0][j];

        for (let i = 1; i < n; i++) {
            if (mat[i][j] === 1) {
                height[i][j] = height[i - 1][j] + 1;
            }
        }
    }

    let ans = 0;

    for (let i = 0; i < n; i++) {
        const row = [...height[i]];

        // Sort heights because columns can be rearranged.
        row.sort((a, b) => b - a);

        for (let j = 0; j < m; j++) {
            ans = Math.max(ans, row[j] * (j + 1));
        }
    }

    return ans;
}

// Driver Code
let mat = [
    [0, 1, 0, 1, 0],
    [0, 1, 0, 1, 1],
    [1, 1, 0, 1, 0]
];
console.log(maxArea(mat));

mat = [
    [0, 1, 0, 1, 0],
    [0, 1, 1, 1, 1],
    [1, 1, 1, 0, 1],
    [1, 1, 1, 1, 1]
];
console.log(maxArea(mat));

Output
6
9

[Expected Approach] Counting Sort on Heights - O(n * (n + m)) Time and O(n * m) Space

The idea is to avoid sorting every row using comparison sort. Since height values can only range from 0 to n, we can count the frequency of each height and rebuild the row in decreasing order using counting sort. Then we calculate the maximum rectangle area for each row.

C++
#include <iostream>
#include <vector>
using namespace std;

int maxArea(vector<vector<int>>& mat) {
    int n = mat.size();
    int m = mat[0].size();

    vector<vector<int>> height(n, vector<int>(m, 0));

    // height[i][j] stores consecutive 1s ending at row i in column j.
    for (int j = 0; j < m; j++) {
        height[0][j] = mat[0][j];

        for (int i = 1; i < n; i++) {
            if (mat[i][j] == 1) {
                height[i][j] = height[i - 1][j] + 1;
            }
        }
    }

    int ans = 0;

    for (int i = 0; i < n; i++) {
        vector<int> count(n + 1, 0);

        // Count frequency of each height.
        for (int j = 0; j < m; j++) {
            count[height[i][j]]++;
        }

        int col = 0;

        // Rearrange heights in decreasing order using counting sort.
        for (int h = n; h >= 0; h--) {
            while (count[h] > 0) {
                height[i][col] = h;
                col++;
                count[h]--;
            }
        }

        // Calculate maximum area for this row.
        for (int j = 0; j < m; j++) {
            ans = max(ans, height[i][j] * (j + 1));
        }
    }

    return ans;
}

int main() {
    vector<vector<int>> mat = {
        {0, 1, 0, 1, 0},
        {0, 1, 0, 1, 1},
        {1, 1, 0, 1, 0}
    };
    cout << maxArea(mat) << endl;

    mat = {
        {0, 1, 0, 1, 0},
        {0, 1, 1, 1, 1},
        {1, 1, 1, 0, 1},
        {1, 1, 1, 1, 1}
    };
    cout << maxArea(mat) << endl;

    return 0;
}
Java
class GFG {
    static int maxArea(int[][] mat) {
        int n = mat.length;
        int m = mat[0].length;

        int[][] height = new int[n][m];

        // height[i][j] stores consecutive 1s ending at row i in column j.
        for (int j = 0; j < m; j++) {
            height[0][j] = mat[0][j];

            for (int i = 1; i < n; i++) {
                if (mat[i][j] == 1) {
                    height[i][j] = height[i - 1][j] + 1;
                }
            }
        }

        int ans = 0;

        for (int i = 0; i < n; i++) {
            int[] count = new int[n + 1];

            // Count frequency of each height.
            for (int j = 0; j < m; j++) {
                count[height[i][j]]++;
            }

            int col = 0;

            // Rearrange heights in decreasing order using counting sort.
            for (int h = n; h >= 0; h--) {
                while (count[h] > 0) {
                    height[i][col] = h;
                    col++;
                    count[h]--;
                }
            }

            // Calculate maximum area for this row.
            for (int j = 0; j < m; j++) {
                ans = Math.max(ans, height[i][j] * (j + 1));
            }
        }

        return ans;
    }

    public static void main(String[] args) {
        int[][] mat = {
            {0, 1, 0, 1, 0},
            {0, 1, 0, 1, 1},
            {1, 1, 0, 1, 0}
        };
        System.out.println(maxArea(mat));

        mat = new int[][] {
            {0, 1, 0, 1, 0},
            {0, 1, 1, 1, 1},
            {1, 1, 1, 0, 1},
            {1, 1, 1, 1, 1}
        };
        System.out.println(maxArea(mat));
    }
}
Python
def maxArea(mat):
    n = len(mat)
    m = len(mat[0])

    height = [[0] * m for _ in range(n)]

    # height[i][j] stores consecutive 1s ending at row i in column j.
    for j in range(m):
        height[0][j] = mat[0][j]

        for i in range(1, n):
            if mat[i][j] == 1:
                height[i][j] = height[i - 1][j] + 1

    ans = 0

    for i in range(n):
        count = [0] * (n + 1)

        # Count frequency of each height.
        for j in range(m):
            count[height[i][j]] += 1

        col = 0

        # Rearrange heights in decreasing order using counting sort.
        for h in range(n, -1, -1):
            while count[h] > 0:
                height[i][col] = h
                col += 1
                count[h] -= 1

        # Calculate maximum area for this row.
        for j in range(m):
            ans = max(ans, height[i][j] * (j + 1))

    return ans


if __name__ == "__main__":
    mat = [
        [0, 1, 0, 1, 0],
        [0, 1, 0, 1, 1],
        [1, 1, 0, 1, 0]
    ]
    print(maxArea(mat))

    mat = [
        [0, 1, 0, 1, 0],
        [0, 1, 1, 1, 1],
        [1, 1, 1, 0, 1],
        [1, 1, 1, 1, 1]
    ]
    print(maxArea(mat))
C#
using System;

class GFG {
    static int maxArea(int[,] mat) {
        int n = mat.GetLength(0);
        int m = mat.GetLength(1);

        int[,] height = new int[n, m];

        // height[i, j] stores consecutive 1s ending at row i in column j.
        for (int j = 0; j < m; j++) {
            height[0, j] = mat[0, j];

            for (int i = 1; i < n; i++) {
                if (mat[i, j] == 1) {
                    height[i, j] = height[i - 1, j] + 1;
                }
            }
        }

        int ans = 0;

        for (int i = 0; i < n; i++) {
            int[] count = new int[n + 1];

            // Count frequency of each height.
            for (int j = 0; j < m; j++) {
                count[height[i, j]]++;
            }

            int col = 0;

            // Rearrange heights in decreasing order using counting sort.
            for (int h = n; h >= 0; h--) {
                while (count[h] > 0) {
                    height[i, col] = h;
                    col++;
                    count[h]--;
                }
            }

            // Calculate maximum area for this row.
            for (int j = 0; j < m; j++) {
                ans = Math.Max(ans, height[i, j] * (j + 1));
            }
        }

        return ans;
    }

    static void Main() {
        int[,] mat = {
            {0, 1, 0, 1, 0},
            {0, 1, 0, 1, 1},
            {1, 1, 0, 1, 0}
        };
        Console.WriteLine(maxArea(mat));

        mat = new int[,] {
            {0, 1, 0, 1, 0},
            {0, 1, 1, 1, 1},
            {1, 1, 1, 0, 1},
            {1, 1, 1, 1, 1}
        };
        Console.WriteLine(maxArea(mat));
    }
}
JavaScript
function maxArea(mat) {
    const n = mat.length;
    const m = mat[0].length;

    const height = Array.from({ length: n }, () => new Array(m).fill(0));

    // height[i][j] stores consecutive 1s ending at row i in column j.
    for (let j = 0; j < m; j++) {
        height[0][j] = mat[0][j];

        for (let i = 1; i < n; i++) {
            if (mat[i][j] === 1) {
                height[i][j] = height[i - 1][j] + 1;
            }
        }
    }

    let ans = 0;

    for (let i = 0; i < n; i++) {
        const count = new Array(n + 1).fill(0);

        // Count frequency of each height.
        for (let j = 0; j < m; j++) {
            count[height[i][j]]++;
        }

        let col = 0;

        // Rearrange heights in decreasing order using counting sort.
        for (let h = n; h >= 0; h--) {
            while (count[h] > 0) {
                height[i][col] = h;
                col++;
                count[h]--;
            }
        }

        // Calculate maximum area for this row.
        for (let j = 0; j < m; j++) {
            ans = Math.max(ans, height[i][j] * (j + 1));
        }
    }

    return ans;
}

// Driver Code
let mat = [
    [0, 1, 0, 1, 0],
    [0, 1, 0, 1, 1],
    [1, 1, 0, 1, 0]
];
console.log(maxArea(mat));

mat = [
    [0, 1, 0, 1, 0],
    [0, 1, 1, 1, 1],
    [1, 1, 1, 0, 1],
    [1, 1, 1, 1, 1]
];
console.log(maxArea(mat));

Output
6
9
Comment