Skip to content

Commit 1e77ff2

Browse files
authored
feat: add solutions for lc No.3548 (#5108)
1 parent 27cb7f2 commit 1e77ff2

7 files changed

Lines changed: 963 additions & 8 deletions

File tree

solution/3500-3599/3548.Equal Sum Grid Partition II/README.md

Lines changed: 328 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)