Get Biggest Three Rhombus Sums in a Grid

medium matrix enumeration top-k

Problem

A rhombus is a square rotated 45°, with its four corners centered on grid cells. Its rhombus sum is the sum of the cells lying on its border. A rhombus may have area 0 — that is just a single cell. Enumerate every rhombus that fits inside the m × n grid, compute each border sum, and return the three largest distinct sums in descending order. If fewer than three distinct values exist, return all of them.

Inputgrid = [[3,4,5,1,3],[3,3,4,2,3],[20,30,200,40,10],[1,5,5,4,1],[4,3,2,2,5]]
Output[228, 216, 211]
The biggest border is 20 + 3 + 200 + 5 = 228 (a small rhombus around the 200); the next two distinct totals are 216 and 211.

def getBiggestThree(grid):
    m, n = len(grid), len(grid[0])
    sums = set()                              # distinct rhombus sums
    for i in range(m):                        # top vertex row
        for j in range(n):                    # top vertex col
            k = 0                             # half-diagonal length
            # grow while all four corners stay in bounds
            while i + 2 * k < m and j - k >= 0 and j + k < n:
                if k == 0:
                    total = grid[i][j]        # area-0 rhombus = one cell
                else:
                    total = 0
                    for s in range(k):        # top -> right edge
                        total += grid[i + s][j + s]
                    for s in range(k):        # right -> bottom edge
                        total += grid[i + k + s][j + k - s]
                    for s in range(k):        # bottom -> left edge
                        total += grid[i + 2 * k - s][j - s]
                    for s in range(k):        # left -> top edge
                        total += grid[i + k - s][j - k + s]
                sums.add(total)
                k += 1
    return sorted(sums, reverse=True)[:3]     # three largest distinct
function getBiggestThree(grid) {
  const m = grid.length, n = grid[0].length;
  const sums = new Set();                     // distinct rhombus sums
  for (let i = 0; i < m; i++) {               // top vertex row
    for (let j = 0; j < n; j++) {             // top vertex col
      let k = 0;                              // half-diagonal length
      // grow while all four corners stay in bounds
      while (i + 2 * k < m && j - k >= 0 && j + k < n) {
        let total;
        if (k === 0) {
          total = grid[i][j];                 // area-0 rhombus = one cell
        } else {
          total = 0;
          for (let s = 0; s < k; s++) total += grid[i + s][j + s];          // top -> right
          for (let s = 0; s < k; s++) total += grid[i + k + s][j + k - s];  // right -> bottom
          for (let s = 0; s < k; s++) total += grid[i + 2 * k - s][j - s];  // bottom -> left
          for (let s = 0; s < k; s++) total += grid[i + k - s][j - k + s];  // left -> top
        }
        sums.add(total);
        k++;
      }
    }
  }
  return [...sums].sort((a, b) => b - a).slice(0, 3); // three largest distinct
}
int[] getBiggestThree(int[][] grid) {
    int m = grid.length, n = grid[0].length;
    TreeSet<Integer> sums = new TreeSet<>();         // distinct, sorted
    for (int i = 0; i < m; i++) {                    // top vertex row
        for (int j = 0; j < n; j++) {               // top vertex col
            int k = 0;                              // half-diagonal length
            // grow while all four corners stay in bounds
            while (i + 2 * k < m && j - k >= 0 && j + k < n) {
                int total;
                if (k == 0) {
                    total = grid[i][j];             // area-0 = one cell
                } else {
                    total = 0;
                    for (int s = 0; s < k; s++) total += grid[i + s][j + s];         // top -> right
                    for (int s = 0; s < k; s++) total += grid[i + k + s][j + k - s]; // right -> bottom
                    for (int s = 0; s < k; s++) total += grid[i + 2 * k - s][j - s]; // bottom -> left
                    for (int s = 0; s < k; s++) total += grid[i + k - s][j - k + s]; // left -> top
                }
                sums.add(total);
                k++;
            }
        }
    }
    int take = Math.min(3, sums.size());
    int[] res = new int[take];
    for (int t = 0; t < take; t++) res[t] = sums.pollLast(); // largest first
    return res;
}
vector<int> getBiggestThree(vector<vector<int>>& grid) {
    int m = grid.size(), n = grid[0].size();
    set<int> sums;                                   // distinct, sorted ascending
    for (int i = 0; i < m; i++) {                    // top vertex row
        for (int j = 0; j < n; j++) {               // top vertex col
            int k = 0;                              // half-diagonal length
            // grow while all four corners stay in bounds
            while (i + 2 * k < m && j - k >= 0 && j + k < n) {
                int total;
                if (k == 0) {
                    total = grid[i][j];             // area-0 = one cell
                } else {
                    total = 0;
                    for (int s = 0; s < k; s++) total += grid[i + s][j + s];         // top -> right
                    for (int s = 0; s < k; s++) total += grid[i + k + s][j + k - s]; // right -> bottom
                    for (int s = 0; s < k; s++) total += grid[i + 2 * k - s][j - s]; // bottom -> left
                    for (int s = 0; s < k; s++) total += grid[i + k - s][j - k + s]; // left -> top
                }
                sums.insert(total);
                k++;
            }
        }
    }
    vector<int> res(sums.rbegin(), sums.rend());     // descending
    if (res.size() > 3) res.resize(3);
    return res;
}
Time: O(m · n · min(m, n)²) Space: O(number of distinct sums)