返回
并查集的奇妙世界——JS中的算法魅力
前端
2024-01-10 17:32:12
前言
算法的世界中,有一种数据结构叫“并查集”,它以其简洁的结构和高效的算法在各种领域大放异彩。今天,我们就来以leetcode中的“岛屿的最大面积”问题为例,一起探究并查集的魅力。
并查集简介
并查集是一种数据结构,可以维护一组元素的集合。它的主要目的是检测两个元素是否属于同一个集合,以及将两个集合合并为一个。并查集有两种基本操作:查找和合并。
- 查找: 查找操作确定一个元素属于哪个集合。
- 合并: 合并操作将两个集合合并为一个集合。
并查集通常使用数组来实现。每个元素在数组中的位置就是其集合的ID。查找操作只需要返回元素所在位置的值即可。合并操作则需要将两个元素所在集合的ID值更新为同一个值,以便将它们合并为一个集合。
并查集在“岛屿的最大面积”问题中的应用
leetcode中的“岛屿的最大面积”问题是这样的:给你一个大小为 m x n 的二进制矩阵 grid 。岛屿是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在 水平或者竖直的四个方向上 相邻。返回 grid 中最大的岛屿的面积。
/**
* 给定一个大小为 m x n 的二进制矩阵 grid 。
* 岛屿是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在 水平或者竖直的四个方向上 相邻。
* 返回 grid 中最大的岛屿的面积。
*
* 示例 1:
* 输入:grid = [[0,0,1,0,0,0,0,1,0,0,0],[0,0,0,0,0,0,0,1,1,1,0],[0,1,1,0,1,0,0,0,0,0,0],[0,1,0,0,1,1,0,0,1,0,0],[0,1,0,0,1,1,0,0,1,1,0],[0,0,0,0,0,0,0,0,0,0,0]]
* 输出:6
*
* 示例 2:
* 输入:grid = [[0,0,0,0,0,0,0,0]]
* 输出:0
*
* 提示:
* m == grid.length
* n == grid[i].length
* 1 <= m, n <= 500
* grid[i][j] 为 0 或 1
*/
const maxAreaOfIsland = (grid) => {
// 定义并查集
const uf = new UnionFind(grid);
// 遍历网格
for (let i = 0; i < grid.length; i++) {
for (let j = 0; j < grid[0].length; j++) {
// 如果当前单元格为陆地
if (grid[i][j] === 1) {
// 与上下左右的陆地合并
if (i > 0 && grid[i - 1][j] === 1) {
uf.union(i * grid[0].length + j, (i - 1) * grid[0].length + j);
}
if (j > 0 && grid[i][j - 1] === 1) {
uf.union(i * grid[0].length + j, i * grid[0].length + j - 1);
}
}
}
}
// 找到最大的岛屿面积
let maxArea = 0;
for (let i = 0; i < grid.length; i++) {
for (let j = 0; j < grid[0].length; j++) {
// 如果当前单元格为陆地
if (grid[i][j] === 1) {
// 获取当前单元格所属集合的面积
const area = uf.getSize(i * grid[0].length + j);
maxArea = Math.max(maxArea, area);
}
}
}
return maxArea;
};
// 并查集类
class UnionFind {
constructor(grid) {
this.parent = [];
this.size = [];
// 初始化并查集
for (let i = 0; i < grid.length * grid[0].length; i++) {
this.parent[i] = i;
this.size[i] = 1;
}
}
// 查找元素的根节点
find(x) {
if (this.parent[x] !== x) {
this.parent[x] = this.find(this.parent[x]);
}
return this.parent[x];
}
// 合并两个集合
union(x, y) {
const rootX = this.find(x);
const rootY = this.find(y);
if (rootX === rootY) {
return;
}
// 将较小集合的根节点指向较大集合的根节点
if (this.size[rootX] < this.size[rootY]) {
this.parent[rootX] = rootY;
this.size[rootY] += this.size[rootX];
} else {
this.parent[rootY] = rootX;
this.size[rootX] += this.size[rootY];
}
}
// 获取集合的面积
getSize(x) {
return this.size[this.find(x)];
}
}
结语
通过“岛屿的最大面积”问题,我们领略了并查集的魅力。并查集是一种非常有用的数据结构,它可以高效地维护一组元素的集合,并支持查找和合并操作。在实际应用中,并查集可以解决各种各样的问题,例如:
- 社交网络中的连通性问题
- 图论中的最小生成树问题
- 图论中的最短路径问题
- 数据压缩问题
希望这篇文章能激发您对算法和数据结构的兴趣,并鼓励您在自己的项目中使用它们。如果您有任何问题或建议,欢迎在评论区留言。