↓快轉到主要內容
  1. LeetCode/

LeetCode 3548: Equal Sum Grid Partition II

·2 分鐘· ·
LeetCode Hard Prefix-Sum Hash-Table Matrix Enumeration
Wei Yi Chung
作者
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
目錄

基本資料
#

難易度: hard 第一次嘗試:2026-07-27

  • 提交紀錄:Accepted ×2

解題思路
#

只寫橫切,直切把矩陣轉置再做一次。切在第 k 列下面時,上面的和用列總和的前綴和累加(Prefix Sum 模板二),差 diff = top - bottom:

  • diff == 0:直接成立。
  • diff > 0:要從上半部去掉一格值剛好是 diff 的格子;diff < 0 則從下半部去掉 -diff。

去掉一格之後那一半還要連通:

那一半的形狀能去掉哪些格子
只有一列(或只有一欄)只能去掉兩端,去掉中間會斷成兩段
至少 2 × 2任何一格都可以

所以要知道「某個值有沒有出現在上半部 / 下半部」:記每個值最早和最晚出現的列。上半部是第 0..k 列,只要最早出現的列 <= k;下半部是第 k+1..m-1 列,只要最晚出現的列 >= k + 1。

我的解法
#

class Solution:
    def canPartitionGrid(self, grid: List[List[int]]) -> bool:
        def check(g):                              # 只試橫切
            m, n = len(g), len(g[0])
            total = sum(map(sum, g))
            first_row, last_row = {}, {}
            for r in range(m):
                for v in g[r]:
                    first_row.setdefault(v, r)
                    last_row[v] = r
            top = 0
            for k in range(m - 1):                 # 切在第 k 列和第 k+1 列之間
                top += sum(g[k])
                diff = top - (total - top)
                if diff == 0:
                    return True
                if diff > 0:                       # 上半部去掉一格 diff
                    if k == 0:                     # 只有一列:只能去掉兩端
                        ok = diff in (g[0][0], g[0][-1])
                    elif n == 1:                   # 只有一欄:只能去掉兩端
                        ok = diff in (g[0][0], g[k][0])
                    else:
                        ok = first_row.get(diff, m) <= k
                else:                              # 下半部去掉一格 -diff
                    if k == m - 2:
                        ok = -diff in (g[-1][0], g[-1][-1])
                    elif n == 1:
                        ok = -diff in (g[k + 1][0], g[-1][0])
                    else:
                        ok = last_row.get(-diff, -1) >= k + 1
                if ok:
                    return True
            return False

        return check(grid) or check([list(col) for col in zip(*grid)])

複雜度
#

時間 O(m · n),空間 O(m · n)(轉置和字典)。

要特別避免的錯誤
#

  • 只有一列或一欄的那一半,去掉中間的格子會斷開,只能去掉兩端。
  • 上半部要看最早出現的列、下半部要看最晚出現的列,不能共用同一個位置。
  • 別忘了直切:轉置之後用同一個函式。

面試口說整理
#

我只處理橫切,直切用轉置。用列總和累加上半部,算出兩邊的差,差要等於較大那一邊某一格的值。那一邊如果只有一列或一欄,只能去掉兩端才不會斷開;否則任何一格都行,所以我記每個值最早和最晚出現的列,判斷它在不在那一半。時間 O(mn)。

相關文章

LeetCode 2122: Recover the Original Array
·2 分鐘
LeetCode Hard Two-Pointers Sorting Hash-Table Enumeration Array
LeetCode 2122 解題筆記:最小的數一定在 lower,枚舉它的配對決定 k;排序後用兩個指針把每個最小的未配對數配給 +2k 的數
LeetCode 980: Unique Paths III
·1 分鐘
LeetCode Hard Backtracking Matrix Dfs
LeetCode 980 解題筆記:網格回溯,原地標記走過的格子,到終點時檢查是否走過所有空格
LeetCode 3989: Maximum Consistent Columns in a Grid
·1 分鐘
LeetCode Hard Dynamic-Programming Matrix Array
LeetCode 3989 解題筆記:保留的欄位是一個子序列,只要相鄰的兩欄相容;LIS 型 DP,dp[j] = 以第 j 欄結尾的最長合法序列
LeetCode 3651: Minimum Cost Path with Teleportations
·2 分鐘
LeetCode Hard Dynamic-Programming Grid-Dp Matrix Array
LeetCode 3651 解題筆記:一層一層算傳送次數;傳送到某格的成本是上一層「值 >= 它的格子」的最小值,排序後用前綴最小值求,再跑一次右 / 下的 Grid DP
LeetCode 1878: Get Biggest Three Rhombus Sums in a Grid
·1 分鐘
LeetCode Medium Matrix Enumeration Heap
LeetCode 1878 解題筆記:枚舉每個頂點和大小,沿四條邊走一圈加總,取前三大的不同值
LeetCode 3910: Count Connected Subgraphs with Even Node Sum
·1 分鐘
LeetCode Hard Bit-Manipulation Enumeration Graph Union-Find
LeetCode 3910 解題筆記:n 很小,用位元遮罩枚舉所有子集合,先檢查和是不是偶數,再檢查誘導子圖是否連通