Skip to content

Commit 28a2168

Browse files
committed
feat: leetcode 827
1 parent 6ae822c commit 28a2168

File tree

8 files changed

+195
-1
lines changed

8 files changed

+195
-1
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<p align="center">
44
<!-- TOPICS COUNT START -->
5-
<img src="https://img.shields.io/badge/-进度:497-green" alt="进度:497">
5+
<img src="https://img.shields.io/badge/-进度:498-green" alt="进度:498">
66
<!-- TOPICS COUNT END -->
77
<a href="./assets/docs/TOPICS.md"><img src="https://img.shields.io/badge/-题库目录-blue" alt="题库目录"></a>
88
<a href="./assets/docs/CATEGORIES.md"><img src="https://img.shields.io/badge/-题库分类-red" alt="题库分类"></a>

assets/data/categories.json

+6
Original file line numberDiff line numberDiff line change
@@ -2267,6 +2267,12 @@
22672267
"path": "./problemset/goat-latin/README.md",
22682268
"difficulty": "简单"
22692269
},
2270+
{
2271+
"id": "827",
2272+
"title": "最大人工岛",
2273+
"path": "./problemset/making-a-large-island/README.md",
2274+
"difficulty": "困难"
2275+
},
22702276
{
22712277
"id": "828",
22722278
"title": "统计子串中的唯一字符",

assets/data/topics.json

+10
Original file line numberDiff line numberDiff line change
@@ -3839,6 +3839,16 @@
38393839
"url": "https://leetcode-cn.com/problems/goat-latin/",
38403840
"path": "./problemset/goat-latin/README.md"
38413841
},
3842+
{
3843+
"id": "827",
3844+
"title": {
3845+
"cn": "最大人工岛",
3846+
"en": "making-a-large-island"
3847+
},
3848+
"difficulty": "困难",
3849+
"url": "https://leetcode.cn/problems/making-a-large-island/",
3850+
"path": "./problemset/making-a-large-island/README.md"
3851+
},
38423852
{
38433853
"id": "828",
38443854
"title": {

assets/docs/CATEGORIES.md

+1
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,7 @@
419419
| 806. [写字符串需要的行数](../../problemset/number-of-lines-to-write-string/README.md) | 简单 |
420420
| 821. [字符的最短距离](../../problemset/shortest-distance-to-a-character/README.md) | 简单 |
421421
| 824. [山羊拉丁文](../../problemset/goat-latin/README.md) | 简单 |
422+
| 827. [最大人工岛](../../problemset/making-a-large-island/README.md) | 困难 |
422423
| 828. [统计子串中的唯一字符](../../problemset/count-unique-characters-of-all-substrings-of-a-given-string/README.md) | 困难 |
423424
| 838. [推多米诺](../../problemset/push-dominoes/README.md) | 中等 |
424425
| 850. [矩形面积 II](../../problemset/rectangle-area-2/README.md) | 困难 |

assets/docs/TOPICS.md

+2
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,8 @@
768768

769769
[824. 山羊拉丁文](../../problemset/goat-latin/README.md)
770770

771+
[827. 最大人工岛](../../problemset/making-a-large-island/README.md)
772+
771773
[828. 统计子串中的唯一字符](../../problemset/count-unique-characters-of-all-substrings-of-a-given-string/README.md)
772774

773775
[829. 连续整数求和](../../problemset/consecutive-numbers-sum/README.md)
+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# 最大人工岛
2+
3+
> 难度:困难
4+
>
5+
> https://leetcode.cn/problems/making-a-large-island/
6+
7+
## 题目
8+
9+
给你一个大小为 `n x n` 二进制矩阵 `grid`**最多** 只能将一格 `0` 变成 `1`
10+
11+
返回执行此操作后,`grid` 中最大的岛屿面积是多少?
12+
13+
岛屿 由一组上、下、左、右四个方向相连的 `1` 形成。
14+
15+
### 示例
16+
17+
#### 示例 1:
18+
19+
```
20+
输入: grid = [[1, 0], [0, 1]]
21+
输出: 3
22+
解释: 将一格0变成1,最终连通两个小岛得到面积为 3 的岛屿。
23+
```
24+
25+
#### 示例 2:
26+
27+
```
28+
输入: grid = [[1, 1], [1, 0]]
29+
输出: 4
30+
解释: 将一格0变成1,岛屿的面积扩大为 4。
31+
```
32+
33+
#### 示例 3:
34+
35+
```
36+
输入: grid = [[1, 1], [1, 1]]
37+
输出: 4
38+
解释: 没有0可以让我们变成1,面积依然为 4。
39+
```
40+
41+
## 解题
42+
43+
```ts
44+
/**
45+
* 标记岛屿 + 合并
46+
* @desc 时间复杂度 O(N²) 空间复杂度 O(N²)
47+
* @param grid
48+
* @returns
49+
*/
50+
export function largestIsland(grid: number[][]): number {
51+
const valid = (n: number, x: number, y: number) => x >= 0 && x < n && y >= 0 && y < n
52+
53+
const d = [0, -1, 0, 1, 0]
54+
const n = grid.length
55+
let res = 0
56+
const tag: number[][] = new Array(n).fill(0).map(() => new Array(n).fill(0))
57+
const area = new Map<number, number>()
58+
for (let i = 0; i < n; i++) {
59+
for (let j = 0; j < n; j++) {
60+
if (grid[i][j] === 1 && tag[i][j] === 0) {
61+
const t = i * n + j + 1
62+
area.set(t, dfs(grid, i, j, tag, t))
63+
res = Math.max(res, area.get(t)!)
64+
}
65+
}
66+
}
67+
for (let i = 0; i < n; i++) {
68+
for (let j = 0; j < n; j++) {
69+
if (grid[i][j] === 0) {
70+
let z = 1
71+
const connected = new Set()
72+
for (let k = 0; k < 4; k++) {
73+
const x = i + d[k]; const y = j + d[k + 1]
74+
if (!valid(n, x, y) || tag[x][y] === 0 || connected.has(tag[x][y]))
75+
continue
76+
77+
z += area.get(tag[x][y])!
78+
connected.add(tag[x][y])
79+
}
80+
res = Math.max(res, z)
81+
}
82+
}
83+
}
84+
return res
85+
86+
function dfs(grid: number[][], x: number, y: number, tag: number[][], t: number) {
87+
const n = grid.length; let res = 1
88+
tag[x][y] = t
89+
for (let i = 0; i < 4; i++) {
90+
const x1 = x + d[i]; const y1 = y + d[i + 1]
91+
if (valid(n, x1, y1) && grid[x1][y1] === 1 && tag[x1][y1] === 0)
92+
res += dfs(grid, x1, y1, tag, t)
93+
}
94+
return res
95+
}
96+
}
97+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { describe, expect, it } from 'vitest'
2+
import { largestIsland } from '.'
3+
4+
describe('最大人工岛', () => {
5+
testCase(largestIsland)
6+
})
7+
8+
function testCase(fn: (grid: number[][]) => number) {
9+
it.each([
10+
[
11+
[[1, 0], [0, 1]],
12+
3,
13+
],
14+
[
15+
[[1, 1], [1, 0]],
16+
4,
17+
],
18+
[
19+
[[1, 1], [1, 1]],
20+
4,
21+
],
22+
])('示例%#', (grid, expected) => {
23+
expect(fn(grid)).toBe(expected)
24+
})
25+
}
+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/**
2+
* 标记岛屿 + 合并
3+
* @desc 时间复杂度 O(N²) 空间复杂度 O(N²)
4+
* @param grid
5+
* @returns
6+
*/
7+
export function largestIsland(grid: number[][]): number {
8+
const valid = (n: number, x: number, y: number) => x >= 0 && x < n && y >= 0 && y < n
9+
10+
const d = [0, -1, 0, 1, 0]
11+
const n = grid.length
12+
let res = 0
13+
const tag: number[][] = new Array(n).fill(0).map(() => new Array(n).fill(0))
14+
const area = new Map<number, number>()
15+
for (let i = 0; i < n; i++) {
16+
for (let j = 0; j < n; j++) {
17+
if (grid[i][j] === 1 && tag[i][j] === 0) {
18+
const t = i * n + j + 1
19+
area.set(t, dfs(grid, i, j, tag, t))
20+
res = Math.max(res, area.get(t)!)
21+
}
22+
}
23+
}
24+
for (let i = 0; i < n; i++) {
25+
for (let j = 0; j < n; j++) {
26+
if (grid[i][j] === 0) {
27+
let z = 1
28+
const connected = new Set()
29+
for (let k = 0; k < 4; k++) {
30+
const x = i + d[k]; const y = j + d[k + 1]
31+
if (!valid(n, x, y) || tag[x][y] === 0 || connected.has(tag[x][y]))
32+
continue
33+
34+
z += area.get(tag[x][y])!
35+
connected.add(tag[x][y])
36+
}
37+
res = Math.max(res, z)
38+
}
39+
}
40+
}
41+
return res
42+
43+
function dfs(grid: number[][], x: number, y: number, tag: number[][], t: number) {
44+
const n = grid.length; let res = 1
45+
tag[x][y] = t
46+
for (let i = 0; i < 4; i++) {
47+
const x1 = x + d[i]; const y1 = y + d[i + 1]
48+
if (valid(n, x1, y1) && grid[x1][y1] === 1 && tag[x1][y1] === 0)
49+
res += dfs(grid, x1, y1, tag, t)
50+
}
51+
return res
52+
}
53+
}

0 commit comments

Comments
 (0)