Welcome to Subscribe On Youtube
3548. Equal Sum Grid Partition II
Description
You are given an m x n matrix grid of positive integers. Your task is to determine if it is possible to make either one horizontal or one vertical cut on the grid such that:
- Each of the two resulting sections formed by the cut is non-empty.
- The sum of elements in both sections is equal, or can be made equal by discounting at most one single cell in total (from either section).
- If a cell is discounted, the rest of the section must remain connected.
Return true if such a partition exists; otherwise, return false.
Note: A section is connected if every cell in it can be reached from any other cell by moving up, down, left, or right through other cells in the section.
Example 1:
Input: grid = [[1,4],[2,3]]
Output: true
Explanation:

- A horizontal cut after the first row gives sums
1 + 4 = 5and2 + 3 = 5, which are equal. Thus, the answer istrue.
Example 2:
Input: grid = [[1,2],[3,4]]
Output: true
Explanation:

- A vertical cut after the first column gives sums
1 + 3 = 4and2 + 4 = 6. - By discounting 2 from the right section (
6 - 2 = 4), both sections have equal sums and remain connected. Thus, the answer istrue.
Example 3:
Input: grid = [[1,2,4],[2,3,5]]
Output: false
Explanation:

- A horizontal cut after the first row gives
1 + 2 + 4 = 7and2 + 3 + 5 = 10. - By discounting 3 from the bottom section (
10 - 3 = 7), both sections have equal sums, but they do not remain connected as it splits the bottom section into two parts ([2]and[5]). Thus, the answer isfalse.
Example 4:
Input: grid = [[4,1,8],[3,2,6]]
Output: false
Explanation:
No valid cut exists, so the answer is false.
Constraints:
1 <= m == grid.length <= 1051 <= n == grid[i].length <= 1052 <= m * n <= 1051 <= grid[i][j] <= 105
Solutions
Solution 1
-
class Solution { public boolean canPartitionGrid(int[][] grid) { return check(grid) || check(rotate(grid)); } private boolean check(int[][] g) { int m = g.length, n = g[0].length; long s1 = 0, s2 = 0; Map<Long, Integer> cnt1 = new HashMap<>(); Map<Long, Integer> cnt2 = new HashMap<>(); for (int[] row : g) { for (int x : row) { s2 += x; cnt2.merge((long) x, 1, Integer::sum); } } for (int i = 0; i < m - 1; i++) { for (int x : g[i]) { s1 += x; s2 -= x; cnt1.merge((long) x, 1, Integer::sum); cnt2.merge((long) x, -1, Integer::sum); } if (s1 == s2) { return true; } if (s1 < s2) { long diff = s2 - s1; if (cnt2.getOrDefault(diff, 0) > 0) { if ((m - i - 1 > 1 && n > 1) || (i == m - 2 && (g[i + 1][0] == diff || g[i + 1][n - 1] == diff)) || (n == 1 && (g[i + 1][0] == diff || g[m - 1][0] == diff))) { return true; } } } else { long diff = s1 - s2; if (cnt1.getOrDefault(diff, 0) > 0) { if ((i + 1 > 1 && n > 1) || (i == 0 && (g[0][0] == diff || g[0][n - 1] == diff)) || (n == 1 && (g[0][0] == diff || g[i][0] == diff))) { return true; } } } } return false; } private int[][] rotate(int[][] grid) { int m = grid.length, n = grid[0].length; int[][] t = new int[n][m]; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { t[j][i] = grid[i][j]; } } return t; } } -
class Solution { public: bool canPartitionGrid(vector<vector<int>>& grid) { return check(grid) || check(rotate(grid)); } private: bool check(const vector<vector<int>>& g) { int m = g.size(), n = g[0].size(); long long s1 = 0, s2 = 0; unordered_map<long long, int> cnt1, cnt2; for (auto& row : g) { for (int x : row) { s2 += x; cnt2[x]++; } } for (int i = 0; i < m - 1; i++) { for (int x : g[i]) { s1 += x; s2 -= x; cnt1[x]++; cnt2[x]--; } if (s1 == s2) return true; if (s1 < s2) { long long diff = s2 - s1; if (cnt2[diff] > 0) { if ( (m - i - 1 > 1 && n > 1) || (i == m - 2 && (g[i + 1][0] == diff || g[i + 1][n - 1] == diff)) || (n == 1 && (g[i + 1][0] == diff || g[m - 1][0] == diff))) return true; } } else { long long diff = s1 - s2; if (cnt1[diff] > 0) { if ( (i + 1 > 1 && n > 1) || (i == 0 && (g[0][0] == diff || g[0][n - 1] == diff)) || (n == 1 && (g[0][0] == diff || g[i][0] == diff))) return true; } } } return false; } vector<vector<int>> rotate(vector<vector<int>>& grid) { int m = grid.size(), n = grid[0].size(); vector<vector<int>> t(n, vector<int>(m)); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { t[j][i] = grid[i][j]; } } return t; } }; -
class Solution: def canPartitionGrid(self, grid: List[List[int]]) -> bool: def check(g: List[List[int]]) -> bool: m, n = len(g), len(g[0]) s1 = s2 = 0 cnt1 = defaultdict(int) cnt2 = defaultdict(int) for i, row in enumerate(g): for j, x in enumerate(row): s2 += x cnt2[x] += 1 for i, row in enumerate(g[: m - 1]): for x in row: s1 += x s2 -= x cnt1[x] += 1 cnt2[x] -= 1 if s1 == s2: return True if s1 < s2: diff = s2 - s1 if cnt2[diff]: if ( (m - i - 1 > 1 and n > 1) or ( i == m - 2 and (g[i + 1][0] == diff or g[i + 1][-1] == diff) ) or (n == 1 and (g[i + 1][0] == diff or g[-1][0] == diff)) ): return True else: diff = s1 - s2 if cnt1[diff]: if ( (i + 1 > 1 and n > 1) or (i == 0 and (g[0][0] == diff or g[0][-1] == diff)) or (n == 1 and (g[0][0] == diff or g[i][0] == diff)) ): return True return False return check(grid) or check(list(zip(*grid))) -
func canPartitionGrid(grid [][]int) bool { return check(grid) || check(rotate(grid)) } func check(g [][]int) bool { m, n := len(g), len(g[0]) var s1, s2 int64 cnt1 := map[int64]int{} cnt2 := map[int64]int{} for _, row := range g { for _, x := range row { v := int64(x) s2 += v cnt2[v]++ } } for i := 0; i < m-1; i++ { for _, x := range g[i] { v := int64(x) s1 += v s2 -= v cnt1[v]++ cnt2[v]-- } if s1 == s2 { return true } if s1 < s2 { diff := s2 - s1 if cnt2[diff] > 0 { if (m-i-1 > 1 && n > 1) || (i == m-2 && (int64(g[i+1][0]) == diff || int64(g[i+1][n-1]) == diff)) || (n == 1 && (int64(g[i+1][0]) == diff || int64(g[m-1][0]) == diff)) { return true } } } else { diff := s1 - s2 if cnt1[diff] > 0 { if (i+1 > 1 && n > 1) || (i == 0 && (int64(g[0][0]) == diff || int64(g[0][n-1]) == diff)) || (n == 1 && (int64(g[0][0]) == diff || int64(g[i][0]) == diff)) { return true } } } } return false } func rotate(grid [][]int) [][]int { m, n := len(grid), len(grid[0]) t := make([][]int, n) for i := range t { t[i] = make([]int, m) } for i := 0; i < m; i++ { for j := 0; j < n; j++ { t[j][i] = grid[i][j] } } return t } -
function canPartitionGrid(grid: number[][]): boolean { return check(grid) || check(rotate(grid)); } function check(g: number[][]): boolean { const m = g.length, n = g[0].length; let s1 = 0, s2 = 0; const cnt1 = new Map<number, number>(); const cnt2 = new Map<number, number>(); for (const row of g) { for (const x of row) { s2 += x; cnt2.set(x, (cnt2.get(x) || 0) + 1); } } for (let i = 0; i < m - 1; i++) { for (const x of g[i]) { s1 += x; s2 -= x; cnt1.set(x, (cnt1.get(x) || 0) + 1); cnt2.set(x, (cnt2.get(x) || 0) - 1); } if (s1 === s2) return true; if (s1 < s2) { const diff = s2 - s1; if ((cnt2.get(diff) || 0) > 0) { if ( (m - i - 1 > 1 && n > 1) || (i === m - 2 && (g[i + 1][0] === diff || g[i + 1][n - 1] === diff)) || (n === 1 && (g[i + 1][0] === diff || g[m - 1][0] === diff)) ) return true; } } else { const diff = s1 - s2; if ((cnt1.get(diff) || 0) > 0) { if ( (i + 1 > 1 && n > 1) || (i === 0 && (g[0][0] === diff || g[0][n - 1] === diff)) || (n === 1 && (g[0][0] === diff || g[i][0] === diff)) ) return true; } } } return false; } function rotate(grid: number[][]): number[][] { const m = grid.length, n = grid[0].length; const t: number[][] = Array.from({ length: n }, () => Array(m).fill(0)); for (let i = 0; i < m; i++) { for (let j = 0; j < n; j++) { t[j][i] = grid[i][j]; } } return t; }