Queries for Largest Square With Limited Ones in a Binary Matrix

Last Updated : 10 Aug, 2026

Given a binary matrix mat[][] and an integer k, process a list of queries queries[][]. Each query contains coordinates [i, j] of the center of a square.

  • For every query, find the side length of the largest odd-sized square centered at cell (i, j) such that the square contains at most k ones.
  • A square centered at (i, j) expands outward symmetrically in all four directions by the same number of cells, so its side length is always odd.

Examples:

Input: mat[][] = [[1,0,1,0,0], [1,0,1,1,1], [1,1,1,1,1], [1,0,0,1,0]], queries[][] = [[1, 2]], k = 9
Output: [3]
Explanation: The largest odd-sized square centered at (1, 2) is the 3 × 3 square spanning rows 0 to 2 and columns 1 to 3. It contains 6 ones, which is at most k = 9. Hence, the answer is 3.

Input: mat[][] = [[1,1,1], [1,1,1], [1,1,1]], queries[][] = [[1, 1], [2, 2]], K = 9
Output: [3, 1]
Explanation: For query (1, 1), the largest valid square is the entire 3 × 3 matrix, which contains 9 ones. Hence, the answer is 3.
For query (2, 2), no expansion is possible without going outside the matrix, so only the 1 × 1 square centered at (2, 2) is valid. Hence, the answer is 1.

Try It Yourself
redirect icon

[Naive Approach] Using Direct Square Sum Computation

The idea is to handle each query independently. Consider each center (i, j), try increasing the square's radius one step at a time. For each size, scan every cell in the current square to compute its sum from scratch.

We use the term radius to denote the number of cells by which a square expands equally in all four directions from its center.

image1

Therefore, if a square has a radius r, its side length is: Side Length = 2 × r + 1.

Working of Approach:

  • For each query (i, j), find the maximum radius the square could expand to without going out of bounds.
  • Try radius 0, 1, 2, ... up to that maximum, one at a time.
  • At each radius, scan every cell in the square and sum the values directly.
  • If the sum exceeds k, stop and use the previous valid radius.
  • Convert the final radius to a side length using 2 * radius + 1, and store it as the answer for this query.
C++
#include <bits/stdc++.h>
using namespace std;

vector<int> largestSquare(vector<vector<int>> &mat, vector<vector<int>> &queries, int k)
{
    int n = mat.size(), m = mat[0].size();
    vector<int> res;

    // Process each query independently.
    for (auto &q : queries)
    {
        int i = q[0], j = q[1];

        // Find the maximum possible radius within matrix boundaries.
        int minDist = min({i, j, n - i - 1, m - j - 1});
        int ans = -1;

        // Try increasing radius and calculate the sum from scratch.
        for (int rad = 0; rad <= minDist; rad++)
        {
            int sum = 0;

            // Calculate the sum of the current square.
            for (int row = i - rad; row <= i + rad; row++)
            {
                for (int col = j - rad; col <= j + rad; col++)
                {
                    sum += mat[row][col];
                }
            }

            // If the sum exceeds k, no larger square is valid.
            if (sum > k)
                break;

            // Radius rad gives a square of side 2 * rad + 1.
            ans = 2 * rad + 1;
        }

        res.push_back(ans);
    }

    return res;
}

int main()
{
    vector<vector<int>> mat = {{1, 1, 1}, {1, 1, 1}, {1, 1, 1}};

    vector<vector<int>> queries = {{1, 1}, {2, 2}};

    int k = 9;

    vector<int> ans = largestSquare(mat, queries, k);

    cout << "[";

    for (int i = 0; i < ans.size(); i++)
    {
        cout << ans[i];

        if (i != ans.size() - 1)
            cout << ", ";
    }

    cout << "]";

    return 0;
}
Java
import java.util.*;

public class GFG {

    public static ArrayList<Integer>
    largestSquare(int[][] mat, int[][] queries, int k)
    {

        int n = mat.length, m = mat[0].length;
        ArrayList<Integer> res = new ArrayList<>();

        // Process each query independently.
        for (int[] q : queries) {
            int i = q[0], j = q[1];

            // Find the maximum possible radius within
            // matrix boundaries.
            int minDist
                = Math.min(Math.min(i, j),
                           Math.min(n - i - 1, m - j - 1));

            int ans = -1;

            // Try increasing radius and calculate the sum
            // from scratch.
            for (int rad = 0; rad <= minDist; rad++) {
                int sum = 0;

                // Calculate the sum of the current square.
                for (int row = i - rad; row <= i + rad;
                     row++) {
                    for (int col = j - rad; col <= j + rad;
                         col++) {
                        sum += mat[row][col];
                    }
                }

                // If the sum exceeds k, no larger square is
                // valid.
                if (sum > k)
                    break;

                // Radius rad gives a square of side 2 * rad
                // + 1.
                ans = 2 * rad + 1;
            }

            res.add(ans);
        }

        return res;
    }

    public static void main(String[] args)
    {

        int[][] mat
            = { { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 } };

        int[][] queries = { { 1, 1 }, { 2, 2 } };

        int k = 9;

        GFG ob = new GFG();

        ArrayList<Integer> ans
            = ob.largestSquare(mat, queries, k);

        System.out.print("[");

        for (int i = 0; i < ans.size(); i++) {
            System.out.print(ans.get(i));

            if (i != ans.size() - 1)
                System.out.print(", ");
        }

        System.out.print("]");
    }
}
Python
def largestSquare(mat, queries, k):
    n = len(mat)
    m = len(mat[0])
    res = []

    # Process each query independently.
    for q in queries:
        i = q[0]
        j = q[1]

        # Find the maximum possible radius within matrix boundaries.
        minDist = min(i, j, n - i - 1, m - j - 1)
        ans = -1

        # Try increasing radius and calculate the sum from scratch.
        for rad in range(minDist + 1):
            sum = 0

            # Calculate the sum of the current square.
            for row in range(i - rad, i + rad + 1):
                for col in range(j - rad, j + rad + 1):
                    sum += mat[row][col]

            # If the sum exceeds k, no larger square is valid.
            if sum > k:
                break

            # Radius rad gives a square of side 2 * rad + 1.
            ans = 2 * rad + 1

        res.append(ans)

    return res


if __name__ == '__main__':
    mat = [[1, 1, 1], [1, 1, 1], [1, 1, 1]]

    queries = [[1, 1], [2, 2]]

    k = 9

    ans = largestSquare(mat, queries, k)

    print('[', end='')

    for i in range(len(ans)):
        print(ans[i], end='')

        if i!= len(ans) - 1:
            print(', ', end='')

    print(']')
C#
using System;
using System.Collections.Generic;

class GFG {
    public List<int> largestSquare(int[][] mat,
                                   int[][] queries, int k)
    {
        int n = mat.Length, m = mat[0].Length;
        List<int> res = new List<int>();

        // Process each query independently.
        foreach(int[] q in queries)
        {
            int i = q[0], j = q[1];

            // Find the maximum possible radius within
            // matrix boundaries.
            int minDist
                = Math.Min(Math.Min(i, j),
                           Math.Min(n - i - 1, m - j - 1));

            int ans = -1;

            // Try increasing radius and calculate the sum
            // from scratch.
            for (int rad = 0; rad <= minDist; rad++) {
                int sum = 0;

                // Calculate the sum of the current square.
                for (int row = i - rad; row <= i + rad;
                     row++) {
                    for (int col = j - rad; col <= j + rad;
                         col++) {
                        sum += mat[row][col];
                    }
                }

                // If the sum exceeds k, no larger square is
                // valid.
                if (sum > k)
                    break;

                // Radius rad gives a square of side 2 * rad
                // + 1.
                ans = 2 * rad + 1;
            }

            res.Add(ans);
        }

        return res;
    }

    static void Main()
    {
        int[][] mat = new int[][] { new int[] { 1, 1, 1 },
                                    new int[] { 1, 1, 1 },
                                    new int[] { 1, 1, 1 } };

        int[][] queries
            = new int[][] { new int[] { 1, 1 },
                            new int[] { 2, 2 } };

        int k = 9;

        GFG obj = new GFG();

        List<int> ans = obj.largestSquare(mat, queries, k);

        Console.Write("[");

        for (int i = 0; i < ans.Count; i++) {
            Console.Write(ans[i]);

            if (i != ans.Count - 1)
                Console.Write(", ");
        }

        Console.Write("]");
    }
}
JavaScript
function largestSquare(mat, queries, k)
{
    let n = mat.length, m = mat[0].length;
    let res = [];

    // Process each query independently.
    for (let q of queries) {
        let i = q[0], j = q[1];

        // Find the maximum possible radius within matrix
        // boundaries.
        let minDist = Math.min(i, j, n - i - 1, m - j - 1);
        let ans = -1;

        // Try increasing radius and calculate the sum from
        // scratch.
        for (let rad = 0; rad <= minDist; rad++) {
            let sum = 0;

            // Calculate the sum of the current square.
            for (let row = i - rad; row <= i + rad; row++) {
                for (let col = j - rad; col <= j + rad;
                     col++) {
                    sum += mat[row][col];
                }
            }

            // If the sum exceeds k, no larger square is
            // valid.
            if (sum > k)
                break;

            // Radius rad gives a square of side 2 * rad
            // + 1.
            ans = 2 * rad + 1;
        }

        res.push(ans);
    }

    return res;
}

// Driver Code
let mat = [ [ 1, 1, 1 ], [ 1, 1, 1 ], [ 1, 1, 1 ] ];

let queries = [ [ 1, 1 ], [ 2, 2 ] ];

let k = 9;

let ans = largestSquare(mat, queries, k);

console.log("[");

for (let i = 0; i < ans.length; i++) {
    console.log(ans[i]);

    if (i != ans.length - 1)
        console.log(", ");
}

console.log("]");

Output
[3, 1]

Time Complexity: O(n * m * q), for each of the q queries, the square can expand up to O(min(n, m)) radii, and at each radius, summing the square scans up to O(radius²) cells. In the worst case, this totals O(n * m) per query.
Auxiliary Space: O(1), apart from the output list, no extra data structures that scale with the input size are used.

The idea is to precompute a 2D prefix sum once, so the sum of any square can be found in O(1) instead of scanning its cells. Since the sum increases as the radius grows, we can use binary search to find the largest valid radius for each query.

  • Use prefix sums for fast square-sum calculation.
  • Binary search the largest radius with sum <= k.

Working of Approach:

  • Build a 1-indexed 2D prefix sum array from the matrix.
  • For each query (i, j), find the maximum radius the square could expand to without going out of bounds.
  • Binary search over the radius: for each candidate radius, use the prefix sum to get the square's total in O(1), and narrow the search based on whether it stays within k.
  • Convert the largest valid radius found to a side length using 2 * radius + 1, and store it as the answer for this query.

Let us understand with an example:
Input: mat[][] = [[1,1,1], [1,1,1], [1,1,1]], queries[][] = [[1, 1], [2, 2]], K = 9

Query (1, 1):

  • minDist = min(1, 1, 1, 1) = 1.
  • Binary search starts with lo = 0, hi = 1.
  • mid = 0, so the square size is 1 × 1.
  • Sum of the square is 1, which is <= 9, so best = 0.
  • Try a larger radius: lo = 1.
  • mid = 1, so the square size is 3 × 3.
  • Sum of the square is 9, which is <= 9, so best = 1.
  • The answer is 2 * 1 + 1 = 3.

Query (2, 2):

  • minDist = min(2, 2, 0, 0) = 0.
  • Binary search starts with lo = 0, hi = 0.
  • mid = 0, so the square size is 1 × 1.
  • Sum of the square is 1, which is <= 9, so best = 0.
  • No larger square can fit inside the matrix.
  • The answer is 2 * 0 + 1 = 1.

Final Output: [3, 1].

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

vector<int> largestSquare(vector<vector<int>> &mat, vector<vector<int>> &queries, int k)
{
    int n = mat.size(), m = mat[0].size();

    // Build a 2D prefix sum array for fast submatrix sum queries.
    vector<vector<int>> prefix(n + 1, vector<int>(m + 1, 0));

    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
        {
            prefix[i + 1][j + 1] = prefix[i][j + 1] + prefix[i + 1][j] - prefix[i][j] + mat[i][j];
        }
    }

    vector<int> res;

    // Process each query independently.
    for (auto &q : queries)
    {
        int i = q[0], j = q[1];

        // Find the maximum possible radius within matrix boundaries.
        int minDist = min({i, j, n - i - 1, m - j - 1});

        // If the center cell itself exceeds k, no valid square exists.
        if (mat[i][j] > k)
        {
            res.push_back(-1);
            continue;
        }

        // Binary search for the largest valid square radius.
        int lo = 0, hi = minDist, best = 0;

        while (lo <= hi)
        {
            int mid = (lo + hi) / 2;

            // Calculate the boundaries of the current square.
            int r1 = i - mid;
            int c1 = j - mid;
            int r2 = i + mid;
            int c2 = j + mid;

            // Find the square sum using the prefix sum array.
            int sum = prefix[r2 + 1][c2 + 1] - prefix[r1][c2 + 1] - prefix[r2 + 1][c1] + prefix[r1][c1];

            // If the sum is within k, try a larger square.
            if (sum <= k)
            {
                best = mid;
                lo = mid + 1;
            }
            else
            {
                // Otherwise, try a smaller square.
                hi = mid - 1;
            }
        }

        // Radius r gives a square of side 2*r + 1.
        res.push_back(2 * best + 1);
    }

    return res;
}

int main()
{
    vector<vector<int>> mat = {{1, 1, 1}, {1, 1, 1}, {1, 1, 1}};

    vector<vector<int>> queries = {{1, 1}, {2, 2}};

    int k = 9;

    vector<int> ans = largestSquare(mat, queries, k);

    cout << "[";
    for (int i = 0; i < ans.size(); i++)
    {
        cout << ans[i];

        if (i != ans.size() - 1)
            cout << ", ";
    }
    cout << "]";

    return 0;
}
Java
import java.util.*;

public class GFG {

    public static ArrayList<Integer>
    largestSquare(int[][] mat, int[][] queries, int k)
    {

        int n = mat.length, m = mat[0].length;

        // Build a 2D prefix sum array for fast submatrix
        // sum queries.
        int[][] prefix = new int[n + 1][m + 1];

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                prefix[i + 1][j + 1]
                    = prefix[i][j + 1] + prefix[i + 1][j]
                      - prefix[i][j] + mat[i][j];
            }
        }

        ArrayList<Integer> res = new ArrayList<>();

        // Process each query independently.
        for (int[] q : queries) {
            int i = q[0], j = q[1];

            // Find the maximum possible radius within
            // matrix boundaries.
            int minDist
                = Math.min(Math.min(i, j),
                           Math.min(n - i - 1, m - j - 1));

            // If the center cell itself exceeds k, no valid
            // square exists.
            if (mat[i][j] > k) {
                res.add(-1);
                continue;
            }

            // Binary search for the largest valid square
            // radius.
            int lo = 0, hi = minDist, best = 0;

            while (lo <= hi) {
                int mid = (lo + hi) / 2;

                // Calculate the boundaries of the current
                // square.
                int r1 = i - mid;
                int c1 = j - mid;
                int r2 = i + mid;
                int c2 = j + mid;

                // Find the square sum using the prefix sum
                // array.
                int sum = prefix[r2 + 1][c2 + 1]
                          - prefix[r1][c2 + 1]
                          - prefix[r2 + 1][c1]
                          + prefix[r1][c1];

                // If the sum is within k, try a larger
                // square.
                if (sum <= k) {
                    best = mid;
                    lo = mid + 1;
                }
                else {
                    // Otherwise, try a smaller square.
                    hi = mid - 1;
                }
            }

            // Radius r gives a square of side 2*r + 1.
            res.add(2 * best + 1);
        }

        return res;
    }

    public static void main(String[] args)
    {

        int[][] mat
            = { { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 } };

        int[][] queries = { { 1, 1 }, { 2, 2 } };

        int k = 9;

        GFG ob = new GFG();

        ArrayList<Integer> ans
            = ob.largestSquare(mat, queries, k);

        System.out.print("[");

        for (int i = 0; i < ans.size(); i++) {
            System.out.print(ans.get(i));

            if (i != ans.size() - 1)
                System.out.print(", ");
        }

        System.out.print("]");
    }
}
Python
def largestSquare(mat, queries, k):
    n = len(mat)
    m = len(mat[0])

    # Build a 2D prefix sum array for fast submatrix sum queries.
    prefix = [[0] * (m + 1) for _ in range(n + 1)]

    for i in range(n):
        for j in range(m):
            prefix[i + 1][j + 1] = prefix[i][j + 1] + prefix[i + 1][j] - prefix[i][j] + mat[i][j]

    res = []

    # Process each query independently.
    for q in queries:
        i = q[0]
        j = q[1]

        # Find the maximum possible radius within matrix boundaries.
        minDist = min(i, j, n - i - 1, m - j - 1)

        # If the center cell itself exceeds k, no valid square exists.
        if mat[i][j] > k:
            res.append(-1)
            continue

        # Binary search for the largest valid square radius.
        lo = 0
        hi = minDist
        best = 0

        while lo <= hi:
            mid = (lo + hi) // 2

            # Calculate the boundaries of the current square.
            r1 = i - mid
            c1 = j - mid
            r2 = i + mid
            c2 = j + mid

            # Find the square sum using the prefix sum array.
            sum = prefix[r2 + 1][c2 + 1] - prefix[r1][c2 + 1] - prefix[r2 + 1][c1] + prefix[r1][c1]

            # If the sum is within k, try a larger square.
            if sum <= k:
                best = mid
                lo = mid + 1
            else:
                # Otherwise, try a smaller square.
                hi = mid - 1

        # Radius r gives a square of side 2*r + 1.
        res.append(2 * best + 1)

    return res


if __name__ == '__main__':
    mat = [[1, 1, 1], [1, 1, 1], [1, 1, 1]]
    queries = [[1, 1], [2, 2]]
    k = 9
    ans = largestSquare(mat, queries, k)
    print('[' + ', '.join(map(str, ans)) + ']')
C#
using System;
using System.Collections.Generic;

class GFG {
    public List<int> largestSquare(int[][] mat,
                                   int[][] queries, int k)
    {
        int n = mat.Length, m = mat[0].Length;

        // Build a 2D prefix sum array for fast submatrix
        // sum queries.
        int[][] prefix = new int[n + 1][];

        for (int i = 0; i <= n; i++)
            prefix[i] = new int[m + 1];

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                prefix[i + 1][j + 1]
                    = prefix[i][j + 1] + prefix[i + 1][j]
                      - prefix[i][j] + mat[i][j];
            }
        }

        List<int> res = new List<int>();

        // Process each query independently.
        foreach(int[] q in queries)
        {
            int i = q[0], j = q[1];

            // Find the maximum possible radius within
            // matrix boundaries.
            int minDist
                = Math.Min(Math.Min(i, j),
                           Math.Min(n - i - 1, m - j - 1));

            // If the center cell itself exceeds k, no valid
            // square exists.
            if (mat[i][j] > k) {
                res.Add(-1);
                continue;
            }

            // Binary search for the largest valid square
            // radius.
            int lo = 0, hi = minDist, best = 0;

            while (lo <= hi) {
                int mid = (lo + hi) / 2;

                // Calculate the boundaries of the current
                // square.
                int r1 = i - mid;
                int c1 = j - mid;
                int r2 = i + mid;
                int c2 = j + mid;

                // Find the square sum using the prefix sum
                // array.
                int sum = prefix[r2 + 1][c2 + 1]
                          - prefix[r1][c2 + 1]
                          - prefix[r2 + 1][c1]
                          + prefix[r1][c1];

                // If the sum is within k, try a larger
                // square.
                if (sum <= k) {
                    best = mid;
                    lo = mid + 1;
                }
                else {
                    // Otherwise, try a smaller square.
                    hi = mid - 1;
                }
            }

            // Radius r gives a square of side 2*r + 1.
            res.Add(2 * best + 1);
        }

        return res;
    }

    static void Main()
    {
        int[][] mat = new int[][] { new int[] { 1, 1, 1 },
                                    new int[] { 1, 1, 1 },
                                    new int[] { 1, 1, 1 } };

        int[][] queries
            = new int[][] { new int[] { 1, 1 },
                            new int[] { 2, 2 } };

        int k = 9;

        GFG obj = new GFG();

        List<int> ans = obj.largestSquare(mat, queries, k);

        Console.Write("[");

        for (int i = 0; i < ans.Count; i++) {
            Console.Write(ans[i]);

            if (i != ans.Count - 1)
                Console.Write(", ");
        }

        Console.Write("]");
    }
}
JavaScript
function largestSquare(mat, queries, k)
{
    const n = mat.length, m = mat[0].length;

    // Build a 2D prefix sum array for fast submatrix sum
    // queries.
    let prefix = Array.from({length : n + 1},
                            () => Array(m + 1).fill(0));

    for (let i = 0; i < n; i++) {
        for (let j = 0; j < m; j++) {
            prefix[i + 1][j + 1]
                = prefix[i][j + 1] + prefix[i + 1][j]
                  - prefix[i][j] + mat[i][j];
        }
    }

    let res = [];

    // Process each query independently.
    for (let q of queries) {
        let i = q[0], j = q[1];

        // Find the maximum possible radius within matrix
        // boundaries.
        let minDist = Math.min(i, j, n - i - 1, m - j - 1);

        // If the center cell itself exceeds k, no valid
        // square exists.
        if (mat[i][j] > k) {
            res.push(-1);
            continue;
        }

        // Binary search for the largest valid square
        // radius.
        let lo = 0, hi = minDist, best = 0;

        while (lo <= hi) {
            let mid = Math.floor((lo + hi) / 2);

            // Calculate the boundaries of the current
            // square.
            let r1 = i - mid;
            let c1 = j - mid;
            let r2 = i + mid;
            let c2 = j + mid;

            // Find the square sum using the prefix sum
            // array.
            let sum = prefix[r2 + 1][c2 + 1]
                      - prefix[r1][c2 + 1]
                      - prefix[r2 + 1][c1] + prefix[r1][c1];

            // If the sum is within k, try a larger square.
            if (sum <= k) {
                best = mid;
                lo = mid + 1;
            }
            else {
                // Otherwise, try a smaller square.
                hi = mid - 1;
            }
        }

        // Radius r gives a square of side 2*r + 1.
        res.push(2 * best + 1);
    }

    return res;
}

// Driver Code
const mat = [ [ 1, 1, 1 ], [ 1, 1, 1 ], [ 1, 1, 1 ] ];
const queries = [ [ 1, 1 ], [ 2, 2 ] ];
const k = 9;
const ans = largestSquare(mat, queries, k);

console.log("[" + ans.join(", ") + "]");

Output
[3, 1]

Time Complexity: O(n * m + q * log(min(n, m))), O(n * m) to build the 2D prefix sum, and each query takes O(log(min(n, m))) due to binary search with O(1) square-sum calculation.
Auxiliary Space: O(n * m), for the 2D prefix sum array.

Comment