LeetCode 417. 太平洋大西洋水流问题题解

417. 太平洋大西洋水流问题

题目来源:417. 太平洋大西洋水流问题

2022.04.27 每日一题

LeetCode 题解持续更新中GitHub仓库地址 CSDN博客地址

今天的题目是深度优先搜素/广度优先搜素的题目,我们需要判断一个网格能否流淌到海洋之中,我们首先想到的就是BFS/DFS进行搜索,但是如果每个格子都进行一次搜索,那么会导致某些格子被多次搜索,最终导致时间超时,那么我们可以更换一下想法,倒着搜索,从通过网格搜索是否可以到达海洋,转变成为从海洋开始搜索,判断可以经过哪些格子,通过的这些格子,就说明该格子可以流到海洋之中,我们只需要搜索两个海洋,并且将可以经过的格子进行标记,最后遍历两个数组,将相应的坐标放入结果数组之中,就可以得到最后的答案。

- 代码之中包含了DFS以及BFS两种,只需要将pacificAtlantic函数中的 dfs 更换成为 bfs 即可两种相互转换。

- 别问为什么不单独写出来,问就是 懒 bushi

class Solution
{
    // 创建两个变量,分别统计数组的大小
    int m = 0, n = 0;
    // 设置方向数组
    vector<vector<int>> dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
    // 设置两个 bool 数组,判断 能否从一个河流流淌到另一个河流
    vector<vector<bool>> pacific, atlantic;

public:
    vector<vector<int>> pacificAtlantic(vector<vector<int>> &heights)
    {
        m = heights.size();
        n = heights[0].size();
        pacific = vector<vector<bool>>(m, vector<bool>(n));
        atlantic = vector<vector<bool>>(m, vector<bool>(n));
        // 分别对靠近海洋周边的进行递归操作
        for (int i = 0; i < m; i++)
        {
            dfs(i, 0, pacific, heights);
            dfs(i, n - 1, atlantic, heights);
        }
        for (int i = 0; i < n; i++)
        {
            dfs(0, i, pacific, heights);
            dfs(m - 1, i, atlantic, heights);
        }
        // 创建结果数组
        vector<vector<int>> res;
        // 遍历两个 布尔数组
        for (int i = 0; i < m; i++)
        {
            for (int j = 0; j < n; j++)
            {
                // 只有当两者都可以相互流淌(两者均为真)的时候才满足条件
                if (atlantic[i][j] && pacific[i][j])
                {
                    res.push_back({i, j});
                }
            }
        }
        return res;
    }

    // 递归函数
    void dfs(int r, int c, vector<vector<bool>> &check, vector<vector<int>> &heights)
    {
        // 如果当前的点已经满足了要求,就返回
        if (check[r][c])
            return;
        // 将当前节点 置为 true 说明 该节点可以被 check 海洋访问
        check[r][c] = true;
        // 遍历四个方向
        for (vector<int> &dir : dirs)
        {
            int xx = r + dir[0], yy = c + dir[1];
            // 不满足要求就 continue
            if (xx < 0 || yy < 0 || xx >= m || yy >= n || heights[xx][yy] < heights[r][c])
                continue;
            dfs(xx, yy, check, heights);
        }
    }

    void bfs(int r, int c, vector<vector<bool>> &check, vector<vector<int>> &heights)
    {
        // 如果当前的点已经满足了要求,就返回
        if (check[r][c])
            return;
        // 将当前节点 置为 true 说明 该节点可以被 check 海洋访问
        check[r][c] = true;
        // 创建 队列,进行迭代操作
        queue<vector<int>> qu;
        qu.push({r, c});
        while (!qu.empty())
        {
            vector<int> temp = qu.front();
            qu.pop();
            for (vector<int> &dir : dirs)
            {
                int xx = temp[0] + dir[0], yy = temp[1] + dir[1];
                // 不满足要求就 continue
                if (xx < 0 || yy < 0 || xx >= m || yy >= n || check[xx][yy] || heights[xx][yy] < heights[temp[0]][temp[1]])
                    continue;
                // 如果满足要求,就将对应的值 赋为 true,并且放入队列中进行 下一次的迭代
                check[xx][yy] = true;
                qu.push({xx, yy});
            }
        }
    }
};
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;

class Solution {
    // 创建两个变量,分别统计数组的大小
    int m = 0, n = 0;
    // 设置方向数组
    int[][] dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
    // 设置两个 bool 数组,判断 能否从一个河流流淌到另一个河流
    boolean[][] pacific, atlantic;

    public List<List<Integer>> pacificAtlantic(int[][] heights) {
        m = heights.length;
        n = heights[0].length;
        pacific = new boolean[m][n];
        atlantic = new boolean[m][n];
        // 分别对靠近海洋周边的进行递归操作
        for (int i = 0; i < m; i++) {
            dfs(i, 0, pacific, heights);
            dfs(i, n - 1, atlantic, heights);
        }
        for (int i = 0; i < n; i++) {
            dfs(0, i, pacific, heights);
            dfs(m - 1, i, atlantic, heights);
        }
        // 创建结果数组
        List<List<Integer>> res = new ArrayList<>();
        // 遍历两个 布尔数组
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                // 只有当两者都可以相互流淌(两者均为真)的时候才满足条件
                if (atlantic[i][j] && pacific[i][j]) {
                    ArrayList<Integer> temp = new ArrayList<>();
                    temp.add(i);
                    temp.add(j);
                    res.add(temp);
                }
            }
        }
        return res;
    }

    // 递归函数
    public void dfs(int r, int c, boolean[][] check, int[][] heights) {
        // 如果当前的点已经满足了要求,就返回
        if (check[r][c]) return;
        // 将当前节点 置为 true 说明 该节点可以被 check 海洋访问
        check[r][c] = true;
        // 遍历四个方向
        for (int[] dir : dirs) {
            int xx = r + dir[0], yy = c + dir[1];
            // 不满足要求就 continue
            if (xx < 0 || yy < 0 || xx >= m || yy >= n || heights[xx][yy] < heights[r][c]) continue;
            dfs(xx, yy, check, heights);
        }
    }

    public void bfs(int r, int c, boolean[][] check, int[][] heights) {
        // 如果当前的点已经满足了要求,就返回
        if (check[r][c]) return;
        // 将当前节点 置为 true 说明 该节点可以被 check 海洋访问
        check[r][c] = true;
        // 创建 队列,进行迭代操作
        Queue<int[]> qu = new ArrayDeque<>();
        qu.offer(new int[]{r, c});
        while (!qu.isEmpty()) {
            int[] temp = qu.poll();
            for (int[] dir : dirs) {
                int xx = temp[0] + dir[0], yy = temp[1] + dir[1];
                // 不满足要求就 continue
                if (xx < 0 || yy < 0 || xx >= m || yy >= n || check[xx][yy] || heights[xx][yy] < heights[temp[0]][temp[1]]) 
                    continue;
                    // 如果满足要求,就将对应的值 赋为 true,并且放入队列中进行 下一次的迭代
                    check[xx][yy] = true;
                    qu.offer(new int[]{xx, yy});
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值