go语言刷题:417. 太平洋大西洋水流问题

题目

有一个 m × n 的矩形岛屿,与 太平洋 和 大西洋 相邻。 “太平洋” 处于大陆的左边界和上边界,而 “大西洋” 处于大陆的右边界和下边界。

这个岛被分割成一个由若干方形单元格组成的网格。给定一个 m x n 的整数矩阵 heights , heights[r][c] 表示坐标 (r, c) 上单元格 高于海平面的高度 。

岛上雨水较多,如果相邻单元格的高度 小于或等于 当前单元格的高度,雨水可以直接向北、南、东、西流向相邻单元格。水可以从海洋附近的任何单元格流入海洋。

返回 网格坐标 result 的 2D列表 ,其中 result[i] = [ri, ci] 表示雨水可以从单元格 (ri, ci) 流向 太平洋和大西洋 。

示例1:

在这里插入图片描述

输入: heights = [[1,2,2,3,5],[3,2,3,4,4],[2,4,5,3,1],[6,7,1,4,5],[5,1,1,2,4]]
输出:[[0,4],[1,3],[1,4],[2,2],[3,0],[3,1],[4,0]]

示例2:

输入: heights = [[2,1],[1,2]]
输出: [[0,0],[0,1],[1,0],[1,1]]

代码:

func dfs(matrix [][]int, row, col int, visited *[][]bool, height int) {

	var direction = [][]int{ //初始化四个方向
		{-1, 0},
		{0, 1},
		{1, 0},
		{0, -1},
	}
	if row < 0 || row >= len(matrix) || col < 0 || col >= len(matrix[0]) { //如果该点坐标超出边界范围直接返回
		return
	}

	if (*visited)[row][col] || matrix[row][col] < height { //如果被访问过 或者 外围点过高则返回
		return
	}

	(*visited)[row][col] = true //设置该点坐标为已经访问

	for i := 0; i < 4; i++ { //遍历该点的四个方向
		dfs(matrix, row+direction[i][0], col+direction[i][1], visited, matrix[row][col])
	}
}

func pacificAtlantic(matrix [][]int) [][]int {

	if len(matrix) == 0 || len(matrix[0]) == 0 { //如果矩阵元素个数为0,则返回空
		return nil
	}

	row, col, result := len(matrix), len(matrix[0]), make([][]int, 0) //获取矩阵长宽
	pacific, atlantic := make([][]bool, row), make([][]bool, row)     //创建矩阵并分配内存
	for i := 0; i < row; i++ {
		pacific[i] = make([]bool, col)
		atlantic[i] = make([]bool, col)
	}

	for i := 0; i < row; i++ {
		for j := 0; j < col; j++ { //寻找边界的点,从矩阵外围往里面找逐渐增高的点
			if i == 0 || j == 0 { //对上侧和左侧矩阵边进行遍历
				dfs(matrix, i, j, &pacific, math.MinInt32)
			}
			if i == row-1 || j == col-1 { //对右侧和下侧的矩阵边进行遍历
				dfs(matrix, i, j, &atlantic, math.MinInt32)
			}
		}
	}

	for i := 0; i < row; i++ {
		for j := 0; j < col; j++ { //再次遍历所有的点,两者都访问才符合条件
			if atlantic[i][j] && pacific[i][j] {
				result = append(result, []int{i, j})
			}
		}
	}
	return result
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值