3546. Equal Sum Grid Partition I

練習日期:2026-03-25

難度:Medium

類型:Array、Matrix、Enumeration、Prefix Sum

📘 題目敘述

給你一個 m x n 的正整數矩陣 grid。我要判斷是否存在一刀水平切割一刀垂直切割,使得:

  • 切完後的兩部分都非空
  • 兩部分元素總和相等

如果可以,回傳 true;否則回傳 false

條件限制

  • 1 <= m == grid.length <= 10^5
  • 1 <= n == grid[i].length <= 10^5
  • 2 <= m * n <= 10^5
  • 1 <= grid[i][j] <= 10^5

🧠 解題思路

我這題的想法很直接:

  • 先算每一列的總和
  • 先算每一行的總和
  • 然後分別嘗試:
  • 水平切一刀
  • 垂直切一刀

如果是水平切,那我其實只是在看:

  • 上半部列總和
  • 下半部列總和

有沒有哪個切點會讓這兩個值相等。

垂直切也是完全一樣的概念,只是改成看行總和。

因為題目保證所有數字都是正數,所以前綴和只會越加越大。 因此當某一邊已經大於另一邊時,後面就不可能再相等了,這時可以直接停止。

所有變數

  • m:列數
  • n:行數
  • hh[i] 表示第 i 列的總和
  • vv[i] 表示第 i 行的總和
  • hsum:所有列總和加起來的值,也就是整個矩陣總和
  • vsum:所有行總和加起來的值,也就是整個矩陣總和
  • sum:暫時用來計算某一列或某一行的總和
  • check:目前前綴部分的總和

🪜 主要流程步驟

1. 先算每一列的總和

我先把每一列的總和存進 h

這樣之後如果我要試某個水平切割,就不用重新掃整個子矩陣, 只要看前面幾列的總和和後面幾列的總和即可。

這裡的 hsum 其實就是整個矩陣總和。


2. 再算每一行的總和

這一步和前面完全對稱,只是改成算每一行的總和。

這樣之後如果我要試垂直切割,就可以直接靠 v 來做前綴加總。

這裡的 vsum 也會等於整個矩陣總和。


3. 先枚舉每個可能的水平切割位置

這裡我讓:

  • check 表示目前上半部的總和
  • hsum 表示目前下半部的總和

每次把第 k 列加到上半部後,就等於在考慮:

  • 上面包含 0 ~ k
  • 下面包含 k + 1 ~ m - 1

如果這時:

  • check == hsum

代表找到一個合法的水平切割,直接回傳 true


4. 為什麼 check > hsum 時可以直接停

else if (check > hsum) {
    break;
}

這一點是因為題目保證矩陣元素全是正數。

所以當我繼續往下加列時:

  • check 只會越來越大
  • hsum 只會越來越小

因此如果某一刻已經有:

  • check > hsum

那後面就不可能再回到相等了,可以直接停止,不用再繼續枚舉。


5. 如果水平切不到,再試垂直切割

這裡完全就是把前面的水平切邏輯,改成用行總和做一次。

現在:

  • check 表示左半部總和
  • vsum 表示右半部總和

每次加上一整行之後,就等於在考慮某個垂直切點。

如果左右相等,就直接回傳 true

如果左邊已經大於右邊,因為所有數字都為正,後面也不可能再相等,所以也可以直接停止。


6. 如果水平和垂直都找不到,就回傳 false

return false;

如果兩種切法都試完,還是沒有任何一個切點能讓兩部分總和相等, 那答案就是 false

⏱️ 複雜度

m = grid.lengthn = grid[0].length

  • 時間複雜度:O(mn + m + n) 先掃整個矩陣算列總和與行總和,再各掃一次列與行前綴。
  • 空間複雜度:O(m + n) 額外用了 hv 兩個陣列來存每列、每行總和。

💻 程式碼實作

class Solution {
public:
    bool canPartitionGrid(vector<vector<int>>& grid) {
        int m = grid.size();
        int n = grid[0].size();
        vector<long long> h(m);
        vector<long long> v(n);
        long long hsum = 0, vsum = 0;
        for (int i = 0; i < m; i++) {
            long long sum = 0;
            for (int j = 0; j < n; j++) {
                sum += grid[i][j];
                hsum += grid[i][j];
            }
            h[i] = sum;
        }
        for (int i = 0; i < n; i++) {
            long long sum = 0;
            for (int j = 0; j < m; j++) {
                sum += grid[j][i];
                vsum += grid[j][i];
            }
            v[i] = sum;
        }
        long long check = 0;
        for (int k = 0; k < m; k++) {
            check += h[k];
            hsum -= h[k];
            if (check == hsum) {
                return true;
            } else if (check > hsum) {
                break;
            }
        }
        check = 0;
        for (int l = 0; l < n; l++) {
            check += v[l];
            vsum -= v[l];
            if (check == vsum) {
                return true;
            } else if (check > vsum) {
                break;
            }
        }
        return false;
    }
};

https://leetcode.com/problems/equal-sum-grid-partition-i/

作者: scottnick
撰寫日期: 2026-03-25
類別:
原文連結: https://scottnick.github.io/cpp-notes/all%20problems/3546-equal-sum-grid-partition-i.html