💡 Using prefix sums helps reduce repeated summations by precomputing cumulative sums, speeding up sum queries for submatrices.
Intuition
Precompute prefix sums for the matrix to quickly calculate sums of rows or sub-rectangles, then use these to compute hourglass sums faster.
Algorithm
- Compute prefix sums for each row to quickly get sums of any 3 consecutive elements in O(1).
- Iterate over all valid hourglass top-left positions.
- Use prefix sums to get top and bottom rows sums quickly.
- Add the middle element explicitly and track the maximum sum.
💡 The key is to reduce repeated addition of the same elements by using prefix sums for rows.
def max_hourglass_sum_prefix(matrix):
n = len(matrix)
m = len(matrix[0])
# Compute prefix sums for each row
prefix = [[0]*(m+1) for _ in range(n)]
for i in range(n):
for j in range(m):
prefix[i][j+1] = prefix[i][j] + matrix[i][j]
max_sum = float('-inf')
for i in range(n - 2):
for j in range(m - 2):
top = prefix[i][j+3] - prefix[i][j]
mid = matrix[i+1][j+1]
bot = prefix[i+2][j+3] - prefix[i+2][j]
current_sum = top + mid + bot
if current_sum > max_sum:
max_sum = current_sum
return max_sum
# Example usage:
matrix = [
[1,2,3,0,0],
[0,0,0,0,0],
[2,1,4,0,0],
[0,0,0,0,0],
[1,1,0,1,0]
]
print(max_hourglass_sum_prefix(matrix)) # Output: 13
Line Notes
prefix = [[0]*(m+1) for _ in range(n)]Create prefix sum array with extra column for easier calculations
prefix[i][j+1] = prefix[i][j] + matrix[i][j]Build prefix sums row-wise to get cumulative sums
top = prefix[i][j+3] - prefix[i][j]Sum top row of hourglass using prefix sums in O(1)
mid = matrix[i+1][j+1]Middle element added explicitly as it's a single element
bot = prefix[i+2][j+3] - prefix[i+2][j]Sum bottom row of hourglass using prefix sums in O(1)
if current_sum > max_sum:Update max_sum if current hourglass sum is greater
public class Solution {
public static int maxHourglassSumPrefix(int[][] matrix) {
int n = matrix.length;
int m = matrix[0].length;
int[][] prefix = new int[n][m+1];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
prefix[i][j+1] = prefix[i][j] + matrix[i][j];
}
}
int maxSum = Integer.MIN_VALUE;
for (int i = 0; i <= n - 3; i++) {
for (int j = 0; j <= m - 3; j++) {
int top = prefix[i][j+3] - prefix[i][j];
int mid = matrix[i+1][j+1];
int bot = prefix[i+2][j+3] - prefix[i+2][j];
int currentSum = top + mid + bot;
if (currentSum > maxSum) {
maxSum = currentSum;
}
}
}
return maxSum;
}
public static void main(String[] args) {
int[][] matrix = {
{1,2,3,0,0},
{0,0,0,0,0},
{2,1,4,0,0},
{0,0,0,0,0},
{1,1,0,1,0}
};
System.out.println(maxHourglassSumPrefix(matrix)); // Output: 13
}
}
Line Notes
int[][] prefix = new int[n][m+1];Create prefix sum array with extra column for easier calculations
prefix[i][j+1] = prefix[i][j] + matrix[i][j];Build prefix sums row-wise for O(1) range sums
int top = prefix[i][j+3] - prefix[i][j];Sum top row of hourglass using prefix sums
int mid = matrix[i+1][j+1];Middle element added explicitly
int bot = prefix[i+2][j+3] - prefix[i+2][j];Sum bottom row of hourglass using prefix sums
if (currentSum > maxSum) {Update maxSum if currentSum is greater
#include <iostream>
#include <vector>
#include <climits>
using namespace std;
int maxHourglassSumPrefix(const vector<vector<int>>& matrix) {
int n = matrix.size();
int m = matrix[0].size();
vector<vector<int>> prefix(n, vector<int>(m+1, 0));
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
prefix[i][j+1] = prefix[i][j] + matrix[i][j];
}
}
int maxSum = INT_MIN;
for (int i = 0; i <= n - 3; i++) {
for (int j = 0; j <= m - 3; j++) {
int top = prefix[i][j+3] - prefix[i][j];
int mid = matrix[i+1][j+1];
int bot = prefix[i+2][j+3] - prefix[i+2][j];
int currentSum = top + mid + bot;
if (currentSum > maxSum) {
maxSum = currentSum;
}
}
}
return maxSum;
}
int main() {
vector<vector<int>> matrix = {
{1,2,3,0,0},
{0,0,0,0,0},
{2,1,4,0,0},
{0,0,0,0,0},
{1,1,0,1,0}
};
cout << maxHourglassSumPrefix(matrix) << endl; // Output: 13
return 0;
}
Line Notes
vector<vector<int>> prefix(n, vector<int>(m+1, 0));Create prefix sum array with extra column for easier calculations
prefix[i][j+1] = prefix[i][j] + matrix[i][j];Build prefix sums row-wise for O(1) range sums
int top = prefix[i][j+3] - prefix[i][j];Sum top row of hourglass using prefix sums
int mid = matrix[i+1][j+1];Middle element added explicitly
int bot = prefix[i+2][j+3] - prefix[i+2][j];Sum bottom row of hourglass using prefix sums
if (currentSum > maxSum) {Update maxSum if currentSum is greater
function maxHourglassSumPrefix(matrix) {
const n = matrix.length;
const m = matrix[0].length;
const prefix = Array.from({length: n}, () => Array(m+1).fill(0));
for (let i = 0; i < n; i++) {
for (let j = 0; j < m; j++) {
prefix[i][j+1] = prefix[i][j] + matrix[i][j];
}
}
let maxSum = Number.NEGATIVE_INFINITY;
for (let i = 0; i <= n - 3; i++) {
for (let j = 0; j <= m - 3; j++) {
const top = prefix[i][j+3] - prefix[i][j];
const mid = matrix[i+1][j+1];
const bot = prefix[i+2][j+3] - prefix[i+2][j];
const currentSum = top + mid + bot;
if (currentSum > maxSum) {
maxSum = currentSum;
}
}
}
return maxSum;
}
// Example usage:
const matrix = [
[1,2,3,0,0],
[0,0,0,0,0],
[2,1,4,0,0],
[0,0,0,0,0],
[1,1,0,1,0]
];
console.log(maxHourglassSumPrefix(matrix)); // Output: 13
Line Notes
const prefix = Array.from({length: n}, () => Array(m+1).fill(0));Create prefix sum array with extra column for easier calculations
prefix[i][j+1] = prefix[i][j] + matrix[i][j];Build prefix sums row-wise for O(1) range sums
const top = prefix[i][j+3] - prefix[i][j];Sum top row of hourglass using prefix sums
const mid = matrix[i+1][j+1];Middle element added explicitly
const bot = prefix[i+2][j+3] - prefix[i+2][j];Sum bottom row of hourglass using prefix sums
if (currentSum > maxSum) {Update maxSum if currentSum is greater
Prefix sums take O(n*m) to compute, then each hourglass sum is computed in O(1), total O(n*m).
💡 This approach is faster for large inputs because it avoids repeated addition inside the nested loops.
Interview Verdict: Accepted
This is a practical optimization over brute force, often expected in interviews to show understanding of prefix sums.