Count Submatrices With All Ones

medium monotonic stack histogram matrix

Problem

Given an m × n binary matrix mat, return the number of submatrices that contain only ones. A submatrix is any contiguous rectangular block of cells, counted once per distinct top-left/bottom-right corner pair.

Inputmat = [[1,0,1],[1,1,0],[1,1,0]]
Output13
6 of size 1×1, 2 of size 1×2, 3 of size 2×1, 1 of size 2×2, 1 of size 3×1 → 13.
Inputmat = [[0,1,1,0],[0,1,1,1],[1,1,1,0]]
Output24
8 + 5 + 2 + 4 + 2 + 2 + 1 = 24 all-ones rectangles.

def numSubmat(mat):
    m, n = len(mat), len(mat[0])
    heights = [0] * n
    total = 0
    for r in range(m):
        for j in range(n):
            heights[j] = heights[j] + 1 if mat[r][j] else 0
        st, summ = [], [0] * n
        for j in range(n):
            while st and heights[st[-1]] >= heights[j]:
                st.pop()
            k = st[-1] if st else -1
            summ[j] = (summ[k] if st else 0) + heights[j] * (j - k)
            st.append(j)
            total += summ[j]
    return total
function numSubmat(mat) {
  const m = mat.length, n = mat[0].length;
  const heights = new Array(n).fill(0);
  let total = 0;
  for (let r = 0; r < m; r++) {
    for (let j = 0; j < n; j++)
      heights[j] = mat[r][j] ? heights[j] + 1 : 0;
    const st = [], summ = new Array(n).fill(0);
    for (let j = 0; j < n; j++) {
      while (st.length && heights[st[st.length - 1]] >= heights[j]) st.pop();
      const k = st.length ? st[st.length - 1] : -1;
      summ[j] = (st.length ? summ[k] : 0) + heights[j] * (j - k);
      st.push(j);
      total += summ[j];
    }
  }
  return total;
}
int numSubmat(int[][] mat) {
    int m = mat.length, n = mat[0].length;
    int[] heights = new int[n];
    int total = 0;
    for (int r = 0; r < m; r++) {
        for (int j = 0; j < n; j++)
            heights[j] = mat[r][j] == 1 ? heights[j] + 1 : 0;
        Deque<Integer> st = new ArrayDeque<>();
        int[] summ = new int[n];
        for (int j = 0; j < n; j++) {
            while (!st.isEmpty() && heights[st.peek()] >= heights[j]) st.pop();
            int k = st.isEmpty() ? -1 : st.peek();
            summ[j] = (st.isEmpty() ? 0 : summ[k]) + heights[j] * (j - k);
            st.push(j);
            total += summ[j];
        }
    }
    return total;
}
int numSubmat(vector<vector<int>>& mat) {
    int m = mat.size(), n = mat[0].size();
    vector<int> heights(n, 0);
    int total = 0;
    for (int r = 0; r < m; r++) {
        for (int j = 0; j < n; j++)
            heights[j] = mat[r][j] ? heights[j] + 1 : 0;
        vector<int> st, summ(n, 0);
        for (int j = 0; j < n; j++) {
            while (!st.empty() && heights[st.back()] >= heights[j]) st.pop_back();
            int k = st.empty() ? -1 : st.back();
            summ[j] = (st.empty() ? 0 : summ[k]) + heights[j] * (j - k);
            st.push_back(j);
            total += summ[j];
        }
    }
    return total;
}
Time: O(m·n) Space: O(n)