岛屿数量

给你一个由’1’(陆地)和 ‘0’(水)组成的的二维网格,请你核算网格中岛屿的数量。

岛屿总是被水围住,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连算法工程师和程序员差异接构成。

此外,你能够假定该网格的四条边均被水围住。

方法一:深度优先查找

为了求出岛屿的数量,咱们能够扫描整个二维网格。假设一个方位为 11,则以其为起始节点初步进行深度优先查找。在深度优先查找的过程中,每个查找算法的有穷性是指到的 1 都会被从头标记为 0。

究竟岛屿的数量便是咱们进行深度优先查找的次数。

class Solution {算法的时刻复杂度取决于
void dfs(char[][] grid, int r, int c) {
int nr = grid.length;
int nc = grid[0].length;
if (r < 0 || c < 0 || r >= nr || c >= nc || grid[r][c] == '0') {
ret算法规划与剖析urn;
}
grid[r][c] = '0';
dfs(grid, r - 1, c);
dfs(grid, r + 1, c);
dfs(grid, r, c - 1);
dfs(grid算法剖析的意图是, r, c + 1);
}
public int numIslands(char[][] grid) {
if (grid == null || gr算法导论id.length == 0) {
return 0;
}
int nr = grid.length;
int nc = gri算法工程师d[0].length;
int num_islands = 0;
for (int r = 0; r < nr; ++r) {
for (int c = 0; c &算法导论lt; nc; ++c) {
if (grid[r][c] == '1') {
++num_islands;
dfs(grid, r, c);
}
}
}
return num_islands;
}
}

时刻复杂度:O(MN),其间 M 和 N 分别为行数和列数。

空间复杂度:O(算法工程师MN),在最坏状况下,整个网格均算法工程师和程序员差异为陆地,深度优先查找的深度抵达 MN。

方法二:广度优先查找

class So算法的有穷性是指lution {
p算法是什么ublic int numIslands(char[][] grid) {
if (grid == null || grid.l算法工程师和程序员差异ength == 0) {
retur算法工程师和程序员差异n 0;
}
int nr = gri算法剖析的意图是d.length;
int算法导论 nc = grid[0].length;
int n算法的五个特性um_islands = 0;
for (int r = 0; r < nr; ++r) {
for (int c =算法 0; c < nc; ++c) {
if (grid[r][c] == '1') {
++num_islands;
g算法rid[r][c] = '0';
Queue<In算法的有穷性是指teger> neighbors = new LinkedLi算法工程师st<>();
neighbors.add(r * nc + c);
while (!neighbors.isEmpty()) {
int id = neighbors.remove();
int row = id /算法的时刻复杂度是指什么 nc;
int col = i算法工程师d %算法的五个特性 nc;
if (row - 1 >= 0 && grid[row-1][算法工程师col] == '1') {
neighbors.add((row-1算法规划与剖析) * nc + col);
grid[row-1][col] = '0';
}算法工程师
if (row + 1 < nr &算法的时刻复杂度是指什么&a算法是什么mp; grid[row+1][col] == '1') {
neighbors.add((row+1) * nc +算法 col);
gr算法是什么id[row+1][col] = '0';
}
if (col - 1 >= 0 && grid[row][col-1] == '1') {
neighbors.add(row * nc算法剖析的意图是 + c算法是什么ol-1算法是什么);
grid[row][col-1] = '0';算法
}
if (col + 1 &lt算法的有穷性是指; nc && grid[row][col+1] == '1') {
n算法工程师和程序员差异ei算法ghb算法规划与剖析or算法导论s.add(row * nc + col+1);
grid[row算法的时刻复杂度是指什么][col+1] = '0';
}
}
}
}
}
return num_islands;
}
}

时刻复杂度:O(MN),其间 M 和 N 分别为行数和列数。

空间复算法工程师杂度:O(min(M,N)),在最坏状况算法剖析的意图是下,整个算法的有穷性是指网格均为陆地,部队的巨细能够抵达 m算法in(M,N)。

方法三:并查集

同样地算法的时刻复杂度取决于,咱们也能够算法的五个特性运用并查集替代查找。

为了求出算法的五个特性岛屿的数量,咱们能够扫描整个二维网格。假设一个方位为 11,算法则将其与相邻四个方向上的 11 在并查会集进行兼并。

究竟岛屿的数量便是并查会集连通重量的数目算法剖析的意图是

下面的动画展示了整个算法

class Solu算法的有穷性是指tion {
class UnionFind {
int算法的有穷性是指 count;
int[] parent;算法导论
int[] rank;
public UnionFi算法导论nd(char[][] grid) {
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) {
if (par算法导论ent[i] != i) parent[i] =算法工程师和程序员差异 find(parent[i]);
return parent[i算法工程师和程序员差异];
}
public void union(int x, int y) {
int rootx = find(x);
int rooty = find(y);
if (rootx != rooty) {
if (rank[rootx] > r算法工程师和程序员差异ank[rooty]) {
parent[rooty] = rootx;
} else if (rank[rootx] < rank[root算法是什么y]) {
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);
f算法规划与剖析or (算法剖析的意图是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();
}
}

用栈结束部队

请你仅运用两个栈结束先入先出部队。部队应当支撑一般部队支撑的一切操作(push、pop、peek、empty):

结束算法是什么 MyQueue 类:

void push(in算法导论t x) 将元素 x 推到部队的结束算法工程师和程序员差异
int pop() 从部队的开端移除并回来元素
int peek() 回来部队开端的元素
boolean empty() 假设部队为空,回来 true ;不然,回来 false

阐明:

你只能运用规范的栈操作 —— 也便是只要push to top,peek/pop from top,size, 和is empty操作算法的有穷性是指是合法的。
你所运用的言语或许不支撑栈。你能够运用 list 或许 deque(双端部队)算法导论来仿照一个栈,只要是规范的栈操作即可。

进阶算法工程师

你能否结束每个操作均摊时刻复杂度为 O(1) 的部队?换句话算法的五个特性说,履行 n 个操作的总时刻复杂度为 O(n) ,即使其间一个操作或许花费较长时刻。

示例:

输入:
[“MyQueue”, “push”, “push”, “peek”, “pop”, “empty”]
[[], [1]算法的五个特性, [2], [], [], []]
输出:
[null, null, null, 1, 1, false]

解说:
MyQueue myQueue = new MyQueue();
m算法工程师和程序员差异yQ算法导论ueue.push(1); // queue is: [1]
myQue算法工程师和程序员差异ue.push(2); // queue is: [1, 2] (leftmost is front of the queu算法剖析的意图是e算法的时刻复杂度是指什么)
myQueue.peek(); // return 1
myQueue.pop(); //算法是什么 return 1, queue is [2]
myQueue.empty(); // return false

提示:

1 <= x <= 9
最多调用 100 次 pu算法规划与剖析sh、pop、peek 和 empty
假定一切操作都是有用的 (例如,一个空的部队不会调用 pop 或许 peek 操作)

双栈

将一个栈当作输入栈,用于压入 push 传入的数据;另一个栈当作输出栈,用于 pop 和 peek 操作。算法是什么

每次 pop 或 peek 时,算法是什么若输出栈为空则将输入栈的悉数数据顺次弹出并压入算法剖析的意图是输出栈,这样输出栈从栈顶往栈底的次第便是部队从队首往队尾的算法次第。

var MyQu算法的时刻复杂度取决于eue = function() {
this.inStack = [];
this.outStack = [];
};
MyQueue.prototype.push = function(x) {
this.inStack.push(x)算法导论;
};
MyQueue.prototype.pop = fun算法导论ction() {
if (!this.算法剖析的意图是outStack算法规划与剖析.length) {
this.in2out();
}
return this.outStack.pop();
};
MyQueue.prototype.peek = function() {
if (!th算法工程师is.outStack.length) {
this.in算法是什么2out();
}
return this.outStack[this.out算法导论Stack.length - 1];
};
MyQueue.算法导论prototype.empty = function() {
return this.outStack.length === 0 && this.inStack.length === 0;
};
MyQueue算法.prototype.in2out = function() {
while (this.inStack.length) {
this.outStack.算法push(this.inStack.pop());
}
}

时刻复杂度:push 和 empty 为 O(1),pop 和 peek 为均摊 O(1)。关于每个元素,至多入栈和出栈各两次,故均摊复杂度为 O(1)。

空间复杂度:O(n)。其间 n 是操作总数。关于有 n 次 push算法是什么 操作的状况,部队中会有 n 个元素,故空间复杂度为 O(n)。