题目1: 孤岛总面积
本例写法比较容易出错。
建议按照题解思路,沿着边先将非孤岛排除。 然后再搜索孤岛数量。
func numIsolatedIsland(_ m: Int, _ n:Int, island: [[Int]]) -> Int {
var visited = Array(repeating: Array(repeating: false, count: n), count: m)
var res = 0
let directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
// 返回是否孤岛
func dfs(_ i: Int, _ j: Int) -> Bool {
guard i >= 0, j >= 0, i < m, j < n, island[i][j] == 1, !visited[i][j] else { return true }
visited[i][j] = true
var isolated = i != 0 && j != 0 && i != (m - 1) && j != (n - 1)
for dir in directions {
let nextI = i + dir.0
let nextJ = j + dir.1
isolated = dfs(nextI, nextJ) && isolated
}
return isolated
}
for i in 0..<m {
for j in 0..<n {
if island[i][j] == 1, !visited[i][j] {
if dfs(i, j) {
res += 1
}
}
}
}
return res
}
// let isolated = numIsolatedIsland(4, 5, island: [[1, 1, 0, 0, 0], [1, 1, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 1, 1]]) //1
let isolated = numIsolatedIsland(4, 5, island: [[0, 0, 0, 0, 0], [0, 1, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 1, 1]]) //1
题目2:沉没孤岛
和上一题孤岛总面积思路类似。
func sinkIsland(_ m: Int, _ n: Int, _ grid: [[Int]] ) {
// 思路更加清楚一些, 先把靠边的岛屿标记为2。
// 然后编译一遍, 把孤岛(1)沉没(改为0), 把靠边的岛(2)恢复(改为1)
var grid = grid
func dfs(_ i: Int, _ j: Int) {
guard i >= 0, j >= 0, i < m, j < n, grid[i][j] == 1 else { return }
grid[i][j] = 2
for dir in [(0, 1), (1, 0), (0, -1), (-1, 0)] {
dfs(i + dir.0, j + dir.1)
}
}
for i in 0..<m {
if grid[i][0] == 1 { dfs(i, 0) }
if grid[i][n - 1] == 1 { dfs(i, n - 1) }
}
for j in 0..<n {
if grid[0][j] == 1 { dfs(0, j) }
if grid[m - 1][j] == 1 { dfs(m, j) }
}
for i in 0..<m {
for j in 0..<n {
if grid[i][j] == 1 { grid[i][j] = 0 }
else if grid[i][j] == 2 { grid[i][j] = 1 }
}
}
print("\(grid)")
}
sinkIsland(4, 5, [[1, 1, 0, 0, 0], [1, 1, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 1, 1]]) //1
题目3:417. 太平洋大西洋水流问题
class Solution {
func pacificAtlantic(_ heights: [[Int]]) -> [[Int]] {
// 巧妙的思路
// 从太平洋 和 大西洋 分别逆流而上, 有重叠的地方即为目标节点。
let m = heights.count
let n = heights[0].count
var firstBoard = Array(repeating: Array(repeating: 0, count: n), count: m)
var secondBoard = Array(repeating: Array(repeating: 0, count: n), count: m)
let directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
func dfs(_ i: Int, _ j: Int, _ board: inout [[Int]]) {
guard board[i][j] == 0 else { return }
board[i][j] = 1
for dir in directions {
let ii = i + dir.0
let jj = j + dir.1
if ii >= 0, jj >= 0, ii < m, jj < n, heights[i][j] <= heights[ii][jj] {
dfs(i + dir.0, j + dir.1, &board)
}
}
}
for i in 0..<m {
dfs(i, 0, &firstBoard)
dfs(i, n - 1, &secondBoard)
}
for j in 0..<n {
dfs(0, j, &firstBoard)
dfs(m - 1, j, &secondBoard)
}
var res = [[Int]]()
for i in 0..<m {
for j in 0..<n {
if firstBoard[i][j] == 1, secondBoard[i][j] == 1 {
res.append([i, j])
}
}
}
return res
}
}
题目4. 建造最大岛屿
func buildMaxIsland(_ m: Int, _ n: Int, _ grid: [[Int]]) -> Int {
// 统计每个岛屿大小
// 然后遍历每个格子, 统计这个格子加上周围岛屿的大小。 找出最大值。
var map = [Int: Int]()
var grid = grid
let directions = [(1, 0), (0, 1), (-1, 0), (0, -1)]
var count = 0
func dfs(_ i: Int, _ j: Int, _ mark: Int) {
guard i >= 0, j >= 0, i < m, j < n, grid[i][j] == 1 else { return }
grid[i][j] = mark
count += 1
for dir in directions {
dfs(i + dir.0, j + dir.1, mark)
}
}
var mark = 2
var allGrid = true
for i in 0..<m {
for j in 0..<n {
if grid[i][j] == 0 { allGrid = false }
if grid[i][j] == 1 {
count = 0
dfs(i, j, mark)
map[mark] = count
mark += 1
}
}
}
if allGrid { return m * n }
var res = 0
var uniqueSet = [Int]()
for i in 0..<m {
for j in 0..<n {
if grid[i][j] != 0 { continue }
var area = 1
uniqueSet.removeAll()
for dir in directions {
let nexti = i + dir.0
let nextj = j + dir.1
guard nexti >= 0, nextj >= 0, nexti < m, nextj < n else { continue }
let islandNum = grid[nexti][nextj]
if islandNum > 0, !uniqueSet.contains(islandNum) {
area += map[islandNum]!
uniqueSet.append(islandNum)
}
}
res = max(res, area)
}
}
return res
}
let area = buildMaxIsland(4, 5, [[1, 1, 0, 0, 0], [1, 1, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 1, 1]]) //6
print("\(area)")