@@ -116,32 +116,356 @@ tags:
116116
117117<!-- solution:start -->
118118
119- ### 方法一
119+ ### 方法一:枚举分割线
120+
121+ 我们可以先枚举水平分割线,计算分割后两部分的元素和,并使用哈希表记录每个部分中元素的出现次数。
122+
123+ 对于每条分割线,我们需要判断两部分的元素和是否相等,或者是否可以通过移除一个单元格使它们相等。如果两部分的元素和相等,那么我们直接返回 $\text{true}$。如果两部分的元素和不相等,我们需要计算它们的差值 $\textit{diff}$,如果 $\textit{diff}$ 在较大部分的哈希表中存在,并且满足移除该单元格后两部分仍然连通的条件,那么我们也返回 $\text{true}$。
124+
125+ 连通性的判断可以通过以下条件来实现:
126+
127+ - 该部分的行数大于 $1$ 且列数大于 $1$。
128+ - 该部分的行数等于 $1$,且移除的单元格位于该部分的边界(即第一列或最后一列)。
129+ - 该部分的行数等于 $1$,且移除的单元格位于该部分的边界(即第一行或最后一行)。
130+
131+ 满足上述条件之一即可保证移除单元格后该部分仍然连通。
132+
133+ 我们还需要枚举垂直分割线,方法与水平分割线类似。为了方便枚举垂直分割线,我们可以先对矩阵进行转置,然后使用相同的逻辑进行判断。
134+
135+ 时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别是矩阵的行数和列数。
120136
121137<!-- tabs:start -->
122138
123139#### Python3
124140
125141``` python
126-
142+ class Solution :
143+ def canPartitionGrid (self , grid : List[List[int ]]) -> bool :
144+ def check (g : List[List[int ]]) -> bool :
145+ m, n = len (g), len (g[0 ])
146+ s1 = s2 = 0
147+ cnt1 = defaultdict(int )
148+ cnt2 = defaultdict(int )
149+ for i, row in enumerate (g):
150+ for j, x in enumerate (row):
151+ s2 += x
152+ cnt2[x] += 1
153+ for i, row in enumerate (g[: m - 1 ]):
154+ for x in row:
155+ s1 += x
156+ s2 -= x
157+ cnt1[x] += 1
158+ cnt2[x] -= 1
159+ if s1 == s2:
160+ return True
161+ if s1 < s2:
162+ diff = s2 - s1
163+ if cnt2[diff]:
164+ if (
165+ (m - i - 1 > 1 and n > 1 )
166+ or (
167+ i == m - 2
168+ and (g[i + 1 ][0 ] == diff or g[i + 1 ][- 1 ] == diff)
169+ )
170+ or (n == 1 and (g[i + 1 ][0 ] == diff or g[- 1 ][0 ] == diff))
171+ ):
172+ return True
173+ else :
174+ diff = s1 - s2
175+ if cnt1[diff]:
176+ if (
177+ (i + 1 > 1 and n > 1 )
178+ or (i == 0 and (g[0 ][0 ] == diff or g[0 ][- 1 ] == diff))
179+ or (n == 1 and (g[0 ][0 ] == diff or g[i][0 ] == diff))
180+ ):
181+ return True
182+ return False
183+
184+ return check(grid) or check(list (zip (* grid)))
127185```
128186
129187#### Java
130188
131189``` java
132-
190+ class Solution {
191+ public boolean canPartitionGrid (int [][] grid ) {
192+ return check(grid) || check(rotate(grid));
193+ }
194+
195+ private boolean check (int [][] g ) {
196+ int m = g. length, n = g[0 ]. length;
197+ long s1 = 0 , s2 = 0 ;
198+
199+ Map<Long , Integer > cnt1 = new HashMap<> ();
200+ Map<Long , Integer > cnt2 = new HashMap<> ();
201+
202+ for (int [] row : g) {
203+ for (int x : row) {
204+ s2 += x;
205+ cnt2. merge((long ) x, 1 , Integer :: sum);
206+ }
207+ }
208+
209+ for (int i = 0 ; i < m - 1 ; i++ ) {
210+ for (int x : g[i]) {
211+ s1 += x;
212+ s2 -= x;
213+
214+ cnt1. merge((long ) x, 1 , Integer :: sum);
215+ cnt2. merge((long ) x, - 1 , Integer :: sum);
216+ }
217+
218+ if (s1 == s2) {
219+ return true ;
220+ }
221+
222+ if (s1 < s2) {
223+ long diff = s2 - s1;
224+ if (cnt2. getOrDefault(diff, 0 ) > 0 ) {
225+ if ((m - i - 1 > 1 && n > 1 )
226+ || (i == m - 2 && (g[i + 1 ][0 ] == diff || g[i + 1 ][n - 1 ] == diff))
227+ || (n == 1 && (g[i + 1 ][0 ] == diff || g[m - 1 ][0 ] == diff))) {
228+ return true ;
229+ }
230+ }
231+ } else {
232+ long diff = s1 - s2;
233+ if (cnt1. getOrDefault(diff, 0 ) > 0 ) {
234+ if ((i + 1 > 1 && n > 1 ) || (i == 0 && (g[0 ][0 ] == diff || g[0 ][n - 1 ] == diff))
235+ || (n == 1 && (g[0 ][0 ] == diff || g[i][0 ] == diff))) {
236+ return true ;
237+ }
238+ }
239+ }
240+ }
241+
242+ return false ;
243+ }
244+
245+ private int [][] rotate (int [][] grid ) {
246+ int m = grid. length, n = grid[0 ]. length;
247+ int [][] t = new int [n][m];
248+ for (int i = 0 ; i < m; i++ ) {
249+ for (int j = 0 ; j < n; j++ ) {
250+ t[j][i] = grid[i][j];
251+ }
252+ }
253+ return t;
254+ }
255+ }
133256```
134257
135258#### C++
136259
137260``` cpp
138-
261+ class Solution {
262+ public:
263+ bool canPartitionGrid(vector<vector<int >>& grid) {
264+ return check(grid) || check(rotate(grid));
265+ }
266+
267+ private:
268+ bool check(const vector<vector<int >>& g) {
269+ int m = g.size(), n = g[ 0] .size();
270+ long long s1 = 0, s2 = 0;
271+
272+ unordered_map<long long, int> cnt1, cnt2;
273+
274+ for (auto& row : g) {
275+ for (int x : row) {
276+ s2 += x;
277+ cnt2[x]++;
278+ }
279+ }
280+
281+ for (int i = 0 ; i < m - 1 ; i++) {
282+ for (int x : g[i]) {
283+ s1 += x;
284+ s2 -= x;
285+ cnt1[x]++;
286+ cnt2[x]--;
287+ }
288+
289+ if (s1 == s2) return true;
290+
291+ if (s1 < s2) {
292+ long long diff = s2 - s1;
293+ if (cnt2[diff] > 0) {
294+ if (
295+ (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;
296+ }
297+ } else {
298+ long long diff = s1 - s2;
299+ if (cnt1[diff] > 0) {
300+ if (
301+ (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;
302+ }
303+ }
304+ }
305+
306+ return false;
307+ }
308+
309+ vector<vector<int>> rotate(vector<vector<int>>& grid) {
310+ int m = grid.size(), n = grid[0].size();
311+ vector<vector<int>> t(n, vector<int>(m));
312+ for (int i = 0; i < m; i++) {
313+ for (int j = 0; j < n; j++) {
314+ t[j][i] = grid[i][j];
315+ }
316+ }
317+ return t;
318+ }
319+ };
139320```
140321
141322#### Go
142323
143324``` go
325+ func canPartitionGrid (grid [][]int ) bool {
326+ return check (grid) || check (rotate (grid))
327+ }
328+
329+ func check (g [][]int ) bool {
330+ m , n := len (g), len (g[0 ])
331+ var s1 , s2 int64
332+
333+ cnt1 := map [int64 ]int {}
334+ cnt2 := map [int64 ]int {}
335+
336+ for _ , row := range g {
337+ for _ , x := range row {
338+ v := int64 (x)
339+ s2 += v
340+ cnt2[v]++
341+ }
342+ }
343+
344+ for i := 0 ; i < m-1 ; i++ {
345+ for _ , x := range g[i] {
346+ v := int64 (x)
347+ s1 += v
348+ s2 -= v
349+ cnt1[v]++
350+ cnt2[v]--
351+ }
352+
353+ if s1 == s2 {
354+ return true
355+ }
356+
357+ if s1 < s2 {
358+ diff := s2 - s1
359+ if cnt2[diff] > 0 {
360+ if (m-i-1 > 1 && n > 1 ) ||
361+ (i == m-2 && (int64 (g[i+1 ][0 ]) == diff || int64 (g[i+1 ][n-1 ]) == diff)) ||
362+ (n == 1 && (int64 (g[i+1 ][0 ]) == diff || int64 (g[m-1 ][0 ]) == diff)) {
363+ return true
364+ }
365+ }
366+ } else {
367+ diff := s1 - s2
368+ if cnt1[diff] > 0 {
369+ if (i+1 > 1 && n > 1 ) ||
370+ (i == 0 && (int64 (g[0 ][0 ]) == diff || int64 (g[0 ][n-1 ]) == diff)) ||
371+ (n == 1 && (int64 (g[0 ][0 ]) == diff || int64 (g[i][0 ]) == diff)) {
372+ return true
373+ }
374+ }
375+ }
376+ }
377+
378+ return false
379+ }
380+
381+ func rotate (grid [][]int ) [][]int {
382+ m , n := len (grid), len (grid[0 ])
383+ t := make ([][]int , n)
384+ for i := range t {
385+ t[i] = make ([]int , m)
386+ }
387+ for i := 0 ; i < m; i++ {
388+ for j := 0 ; j < n; j++ {
389+ t[j][i] = grid[i][j]
390+ }
391+ }
392+ return t
393+ }
394+ ```
144395
396+ #### TypeScript
397+
398+ ``` ts
399+ function canPartitionGrid(grid : number [][]): boolean {
400+ return check (grid ) || check (rotate (grid ));
401+ }
402+
403+ function check(g : number [][]): boolean {
404+ const m = g .length ,
405+ n = g [0 ].length ;
406+ let s1 = 0 ,
407+ s2 = 0 ;
408+
409+ const cnt1 = new Map <number , number >();
410+ const cnt2 = new Map <number , number >();
411+
412+ for (const row of g ) {
413+ for (const x of row ) {
414+ s2 += x ;
415+ cnt2 .set (x , (cnt2 .get (x ) || 0 ) + 1 );
416+ }
417+ }
418+
419+ for (let i = 0 ; i < m - 1 ; i ++ ) {
420+ for (const x of g [i ]) {
421+ s1 += x ;
422+ s2 -= x ;
423+
424+ cnt1 .set (x , (cnt1 .get (x ) || 0 ) + 1 );
425+ cnt2 .set (x , (cnt2 .get (x ) || 0 ) - 1 );
426+ }
427+
428+ if (s1 === s2 ) return true ;
429+
430+ if (s1 < s2 ) {
431+ const diff = s2 - s1 ;
432+ if ((cnt2 .get (diff ) || 0 ) > 0 ) {
433+ if (
434+ (m - i - 1 > 1 && n > 1 ) ||
435+ (i === m - 2 && (g [i + 1 ][0 ] === diff || g [i + 1 ][n - 1 ] === diff )) ||
436+ (n === 1 && (g [i + 1 ][0 ] === diff || g [m - 1 ][0 ] === diff ))
437+ )
438+ return true ;
439+ }
440+ } else {
441+ const diff = s1 - s2 ;
442+ if ((cnt1 .get (diff ) || 0 ) > 0 ) {
443+ if (
444+ (i + 1 > 1 && n > 1 ) ||
445+ (i === 0 && (g [0 ][0 ] === diff || g [0 ][n - 1 ] === diff )) ||
446+ (n === 1 && (g [0 ][0 ] === diff || g [i ][0 ] === diff ))
447+ )
448+ return true ;
449+ }
450+ }
451+ }
452+
453+ return false ;
454+ }
455+
456+ function rotate(grid : number [][]): number [][] {
457+ const m = grid .length ,
458+ n = grid [0 ].length ;
459+ const t: number [][] = Array .from ({ length: n }, () => Array (m ).fill (0 ));
460+
461+ for (let i = 0 ; i < m ; i ++ ) {
462+ for (let j = 0 ; j < n ; j ++ ) {
463+ t [j ][i ] = grid [i ][j ];
464+ }
465+ }
466+
467+ return t ;
468+ }
145469```
146470
147471<!-- tabs:end -->
0 commit comments