Leetcode-200. 岛屿数量
给定一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,计算岛屿的数量。一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设网格的四个边均被水包围。
示例 1:
输入:
11110
11010
11000
00000
输出: 1
示例 2:
输入:
11000
11000
00100
00011
输出: 3
解法:1. 染色(flood fill)a. 遍历所有的节点,如果节点为1,count++,然后将这个节点和附近的所有1节点全部变为0,使用dfs或者bfs 2. 并查集,a. 初始化,针对所有的1节点,将root指向自己,b. 遍历所有的节点,相邻的1节点合并,0不做处理,c. 遍历查询有多少不同的parent,时间复杂度O(MN)
- Java
dfs
class Solution {
public int numIslands(char[][] grid) {
int count = 0;
for (int i=0;i<grid.length;i++) {
for (int j=0;j<grid[0].length;j++) {
if (grid[i][j]=='1') {
this.dfs(grid, i, j);
count += 1;
}
}
}
return count;
}
public void dfs(char[][] grid, int i, int j) {
if (i<0 || i>= grid.length || j<0 || j>= grid[0].length || grid[i][j]!='1') return ;
grid[i][j] = 0;
this.dfs(grid, i+1, j);
this.dfs(grid, i, j+1);
this.dfs(grid, i-1, j);
this.dfs(grid, i, j-1);
return ;
}
}
- Java
bfs
class Solution {
int[] dx = {
0,0,-1,1};
int[] dy = {
-1,1,0,0};
public int numIslands(char[][] grid) {
int count=0;
for(int i=0;i<grid.length;i++)
for(int j=0;j<grid[0].length;j++){
if(grid[i][j]=='1'){
bfsFill(grid,i,j);
count++;
}
}
return count;
}
private void bfsFill(char[][] grid,int x, int y){
grid[x][y]='0';
int n = grid.length;
int m = grid[0].length;
Queue<Integer> queue = new LinkedList<Integer>();
int code = x*m+y;
queue.offer(code);
while(!queue.isEmpty())
{
code = queue.poll();
int i = code/m;
int j = code%m;
for (int k=0;k<4;k++) {
if (this.isValid(grid, i+dx[k], j+dy[k])) {
queue.offer((i+dx[k])*m+(j+dy[k]));
grid[i+dx[k]][j+dy[k]] = '0';
}
}
}
}
public boolean isValid(char[][] grid,int i,int j) {
return (i>=0 && i<grid.length && j>=0 && j<grid[0].length && grid[i][j]=='1');
}
}
并查集
class Solution {
class UnionFind {
int count; // # of connected components
int[] parent;
int[] rank;
public UnionFind(char[][] grid) {
// for problem 200
count = 0;
int m = grid.length;
int n = grid[0].length;
parent = new int[m * n];
rank = new int[m * n];
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (grid[i][j] == '1') {
parent[i * n + j] = i * n + j;
++count;
}
rank[i * n + j] = 0;
}
}
}
public int find(int i) {
// path compression
if (parent[i] != i) parent[i] = find(parent[i]);
return parent[i];
}
public void union(int x, int y) {
// union with rank
int rootx = find(x);
int rooty = find(y);
if (rootx != rooty) {
if (rank[rootx] > rank[rooty]) {
parent[rooty] = rootx;
} else if (rank[rootx] < rank[rooty]) {
parent[rootx] = rooty;
} else {
parent[rooty] = rootx; rank[rootx] += 1;
}
--count;
}
}
public int getCount() {
return count;
}
}
public int numIslands(char[][] grid) {
if (grid == null || grid.length == 0) {
return 0;
}
int nr = grid.length;
int nc = grid[0].length;
int num_islands = 0;
UnionFind uf = new UnionFind(grid);
for (int r = 0; r < nr; ++r) {
for (int c = 0; c < nc; ++c) {
if (grid[r][c] == '1') {
grid[r][c] = '0';
if (r - 1 >= 0 && grid[r-1][c] == '1') {
uf.union(r * nc + c, (r-1) * nc + c);
}
if (r + 1 < nr && grid[r+1][c] == '1') {
uf.union(r * nc + c, (r+1) * nc + c);
}
if (c - 1 >= 0 && grid[r][c-1] == '1') {
uf.union(r * nc + c, r * nc + c - 1);
}
if (c + 1 < nc && grid[r][c+1] == '1') {
uf.union(r * nc + c, r * nc + c + 1);
}
}
}
}
return uf.getCount();
}
}
- Python
dfs
class Solution:
def numIslands(self, grid: List[List[str]]) -> int:
self.grid = grid
count = 0
for i in range(len(grid)):
for j in range(len(grid[0])):
if (grid[i][j]=='1'):
self.dfs(i, j)
count += 1
return count
def dfs(self, i, j):
if i<0 or i>=len(self.grid) or j<0 or j>=len(self.grid[0]) or self.grid[i][j]!='1' : return
self.grid[i][j] = 0
self.dfs(i-1, j)
self.dfs(i+1, j)
self.dfs(i, j-1)
self.dfs(i, j+1)
- Python
bfs
class Solution:
def numIslands(self, grid: List[List[str]]) -> int:
self.dx = [0,0,-1,1]
self.dy = [-1,1,0,0]
if not grid: return 0
self.grid = grid
count = 0
for i in range(len(self.grid)):
for j in range(len(self.grid[0])):
if (grid[i][j]=='1'):
self.bfs(i, j)
count += 1
return count
def bfs(self, i, j):
self.queue = [(i,j)]
while self.queue:
i, j = self.queue.pop(0)
for k in range(4):
if self.isValid(i+self.dx[k], j+self.dy[k]):
self.queue.append((i+self.dx[k], j+self.dy[k]))
self.grid[i+self.dx[k]][j+self.dy[k]] = '0'
def isValid(self, i, j):
return 0<=i<len(self.grid) and 0<=j<len(self.grid[0]) and self.grid[i][j]=='1'
并查集
class UnionFind(object):
def __init__(self, grid):
m, n = len(grid), len(grid[0])
self.count = 0
self.parent = [-1] * (m*n)
self.rank = [0] * (m*n)
for i in range(m):
for j in range(n):
if grid[i][j] == '1':
self.parent[i*n+j] = i*n+j
self.count += 1
def find(self, i):
if self.parent[i]!= i:
self.parent[i] = self.find(self.parent[i])
return self.parent[i]
def union(self, x, y):
rootx = self.find(x)
rooty = self.find(y)
if rootx!=rooty:
if self.rank[rootx]>self.rank[rooty]:
self.parent[rooty] = rootx
elif self.rank[rooty]>self.rank[rootx]:
self.parent[rootx] = rooty
else:
self.parent[rooty] = rootx
self.rank[rootx] += 1
self.count -= 1
class Solution:
def numIslands(self, grid: List[List[str]]) -> int:
if not grid : return 0
uf = UnionFind(grid)
directions = [(0, 1), (0, -1), (-1, 0), (1, 0)]
m, n = len(grid), len(grid[0])
for i in range(m):
for j in range(n):
if grid[i][j]=='0':continue
for d in directions:
x, y = i+d[0], j+d[1]
if 0<=x<m and 0<=y<n and grid[x][y]=='1':
uf.union(i*n+j, x*n+y)
return uf.count
Leetcode-547. 朋友圈
班上有 N 名学生。其中有些人是朋友,有些则不是。他们的友谊具有是传递性。如果已知 A 是 B 的朋友,B 是 C 的朋友,那么我们可以认为 A 也是 C 的朋友。所谓的朋友圈,是指所有朋友的集合。
给定一个 N * N 的矩阵 M,表示班级中学生之间的朋友关系。如果M[i][j] = 1,表示已知第 i 个和 j 个学生互为朋友关系,否则为不知道。你必须输出所有学生中的已知的朋友圈总数。
示例 1:
输入:
[[1,1,0],
[1,1,0],
[0,0,1]]
输出: 2
说明:已知学生0和学生1互为朋友,他们在一个朋友圈。
第2个学生自己在一个朋友圈。所以返回2。
示例 2:
输入:
[[1,1,0],
[1,1,1],
[0,1,1]]
输出: 1
说明:已知学生0和学生1互为朋友,学生1和学生2互为朋友,所以学生0和学生2也是朋友,所以他们三个在一个朋友圈,返回1。
注意:
- N 在[1,200]的范围内。
- 对于所有学生,有M[i][i] = 1。
- 如果有M[i][j] = 1,则有M[j][i] = 1。
解法:1. dfs,遍历层,如果层被访问过,则count+1,visited[i] = 1。时间复杂度O(N^2),空间复杂度O(N)
- Java
dfs
class Solution {
public int findCircleNum(int[][] M) {
int count = 0;
int[] visited = new int[M.length];
for (int i=0;i<M.length;i++) {
if (visited[i]==0) {
this.dfs(M, visited, i);
count++;
}
}
return count;
}
public void dfs(int[][] M, int[] visited, int i) {
for (int j=0;j<M[0].length;j++) {
if (M[i][j]==1 && visited[j]==0) {
visited[j] = 1;
this.dfs(M, visited, j);
}
}
}
}
-bfs
public class Solution {
public int findCircleNum(int[][] M) {
int[] visited = new int[M.length];
int count = 0;
Queue < Integer > queue = new LinkedList < > ();
for (int i = 0; i < M.length; i++) {
if (visited[i] == 0) {
queue.add(i);
while (!queue.isEmpty()) {
int s = queue.remove();
visited[s] = 1;
for (int j = 0; j < M.length; j++) {
if (M[s][j] == 1 && visited[j] == 0)
queue.add(j);
}
}
count++;
}
}
return count;
}
}
- 并查集(慢,不推荐)
public class Solution {
int find(int parent[], int i) {
if (parent[i] == -1)
return i;
return find(parent, parent[i]);
}
void union(int parent[], int x, int y) {
int xset = find(parent, x);
int yset = find(parent, y);
if (xset != yset)
parent[xset] = yset;
}
public int findCircleNum(int[][] M) {
int[] parent = new int[M.length];
Arrays.fill(parent, -1);
for (int i = 0; i < M.length; i++) {
for (int j = 0; j < M.length; j++) {
if (M[i][j] == 1 && i != j) {
union(parent, i, j);
}
}
}
int count = 0;
for (int i = 0; i < parent.length; i++) {
if (parent[i] == -1)
count++;
}
return count;
}
}
作者:LeetCode
链接:https://leetcode-cn.com/problems/friend-circles/solution/peng-you-quan-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
- Python
dfs
class Solution:
def findCircleNum(self, M: List[List[int]]) -> int:
self.visited = [0] * len(M)
count = 0
for i in range(len(M)):
if self.visited[i]==0:
self.dfs(M, i)
count += 1
return count
def dfs(self, M, i):
for j in range(len(M)):
if M[i][j]==1 and self.visited[j]==0:
self.visited[j] = 1
self.dfs(M, j)
- bfs
class Solution:
def findCircleNum(self, M: List[List[int]]) -> int:
if not M:return 0
count = 0
visited = [0]*len(M)
queue = []
for i in range(len(M)):
if visited[i]==0:
queue.append(i)
while queue:
level = queue.pop(0)
visited[level] = 1
for j in range(len(M)):
if M[level][j]==1 and visited[j]==0:
queue.append(j)
count += 1
return count