All topics
26

Summing any rectangle in one step

Tier 1Free

Where it runs

1. The problem

Lesson 24 gave you the sum of any stretch of a plain list with one subtraction. For that, it computed prefix sums (running totals) in advance. Grids raise the same question in two dimensions. You have a grid of numbers. What is the total inside a rectangle: a block of pixels, a range of cells in a spreadsheet, an area of a heatmap? The slow way adds up every cell of the rectangle, which costs O(rows × cols) per query (rows is the number of rows, cols the number of columns). With thousands of queries that is hopeless. The 2D prefix sum builds a table once. After that it answers any rectangle of any size with four reads from the table.

2. In plain words

Take the grid [[1,2,3],[4,5,6],[7,8,9]] and the question: what is the sum of the bottom-right 2 × 2 square, the numbers 5, 6, 8, 9? You could add them up again for every question. Or you could write down once, in every cell, the sum of the whole rectangle from the grid's top-left corner to that cell.

Then any piece is built from four of those sums. Take the big sum down to the bottom-right corner of the piece. Subtract the strip above the piece. Subtract the strip to the left of the piece. The block above and to the left of the piece was in both strips, so it was subtracted twice. Add it back once. Four numbers, whatever the size of the piece.

3. The idea

In advance, compute one running total for each cell: the sum of the whole rectangle from the grid's top-left corner to that cell. Store these totals in a table P. Add a row of zeros on top of it and a column of zeros on its left. Then the formulas never reach index -1. In this table, P[i+1][j+1] holds the sum from the corner to the cell (i,j).

The table is filled by inclusion-exclusion. The block that ends at (i,j) consists of the cell itself, the block right above it and the block right to its left. Those two blocks overlap in the top-left block, so it was counted twice. Subtract it once:

P[i+1][j+1] = matrix[i][j] + P[i][j+1] + P[i+1][j] - P[i][j]

Once P is built, the sum of a rectangle uses the same idea in reverse. Let the top-left corner of the rectangle be (r1,c1) and the bottom-right corner (r2,c2), both included. Take the big block down to the bottom-right corner. Subtract the strip above the rectangle. Subtract the strip to its left. You just subtracted the top-left block twice, so add it back:

P[r2+1][c2+1] - P[r1][c2+1] - P[r2+1][c1] + P[r1][c1]

target big block (to bottom-right) − top strip − left strip + top-left overlap (added back)

Trace it on the grid [[1,2,3],[4,5,6],[7,8,9]]. The query is the bottom-right 2 × 2 square, (1,1) to (2,2). It holds the cells 5, 6, 8, 9, total 28. By the formula:

  • P[3][3] is the whole grid, 45.
  • P[1][3] is the top row, 1 + 2 + 3 = 6.
  • P[3][1] is the left column, 1 + 4 + 7 = 12.
  • P[1][1] is the top-left cell, 1.

45 - 6 - 12 + 1 = 28. Four reads from the table, whether the rectangle has four cells or four million.

4. What it costs

Building P costs O(rows × cols) and happens once. After that each query costs O(1): four reads from the table and three additions or subtractions. For q queries the total is O(rows × cols + q). Adding up the cells again for every query would cost O(q × rows × cols). Memory is O(rows × cols) for the table. The trade is the same as with one-dimensional prefix sums, now in two dimensions: compute once in advance, and then every range question is answered at once.

6. Where this shows up

Integral images in computer vision: fast blurring, feature detection, and finding a small picture inside a bigger one. Totals by area in analytics dashboards and OLAP cubes (multi-dimensional tables for reports). Collision and density queries on a spatial grid. Any sum or average over a rectangle that a user can select. All the lessons on prefix sums lead here. When the same range is queried many times, running totals computed in advance turn each query from a pass over the data into simple arithmetic. Inclusion-exclusion carries the method into two dimensions and beyond.

On LeetCode

Problems about the sum of a rectangle inside a grid, asked many times or for every cell. Build the 2D table of corner sums once, and every rectangle costs four reads.

Your task (Tier 1)

Write the function rectangleSums(matrix, queries).

You get a grid of numbers and a list of questions. Each question asks for the sum of the numbers inside one rectangle of the grid. Answer every question.

  • Input: matrix, a grid of numbers (a list of rows), and queries, a list of questions. Each question is [r1, c1, r2, c2]. The top-left corner is row r1, column c1. The bottom-right corner is row r2, column c2. Both corners belong to the rectangle. Example: [[1,2,3],[4,5,6],[7,8,9]] with the question [0, 0, 1, 1].
  • Return: a list with one sum per question, in the same order.

Steps:

  1. Build a helper table of sums, so that you don't add up the same cell again and again. Make it one row taller and one column wider than the grid, and fill it with 0. The extra top row and left column save you the checks at the edges.
  2. Fill the table so that each cell holds the sum of all grid cells above it and to its left, together with its own grid cell.
  3. For each question, take four values from the table and add and subtract them to get the sum of the rectangle. Add each sum to the result list.

Done when all tests pass:

  • grid [[1,2,3],[4,5,6],[7,8,9]], question [0,0,0,0] -> [1] (one cell)
  • the same grid, question [0,0,2,2] -> [45] (the whole grid)
  • the same grid, question [1,1,2,2] -> [28] (the bottom-right 2 by 2 square)
  • the same grid, question [0,0,1,1] -> [12] (the top-left 2 by 2 square)
  • the same grid, questions [2,0,2,2] and [0,2,2,2] -> [24, 18] (the last row, then the last column)
  • the same grid, questions [0,0,0,0], [1,1,1,1], [0,0,2,2] -> [1, 5, 45] (three questions at once)
  • grid [], no questions [] -> [] (empty grid, must not crash)

Practice

2D prefix sums: the sum of any rectangle in O(1)

rectangleSums(matrix, queries) -> number[] (each query [r1,c1,r2,c2] inclusive corners)

export function rectangleSums(matrix, queries) {
  // Your code here. The task is described in the box above the editor.
}

Running as a guest

The tests run right here, no account needed. Your code is kept in this browser only. A free account keeps it on every device, marks the step done and shows where you are in the course.

Hint ladder

Stuck? Reveal one rung at a time, but try it yourself first.

    We use necessary cookies to run the site (sign-in and language). If you accept, we also load Google Analytics to see which pages are used, and Google reCAPTCHA to keep spam off the contact and bug-report forms. Privacy policy