417. The Pacific-Atlantic Current Problem: Graph Traversal Application Problems

Get into the habit of writing together! This is the 27th day of my participation in the "Nuggets Daily New Plan · April Update Challenge", click to view the details of the event .

Topic description

This is 417. Pacific-Atlantic Currents problem on LeetCode , medium .

Tag : 「DFS」、「BFS」、「多源 BFS」

There is m × na rectangular island adjacent to the Pacific and Atlantic Oceans. The "Pacific" is on the left and upper boundaries of the continent, while the "Atlantic" is on the right and lower boundaries of the continent.

The island is divided into a grid of square cells. Given m x nan  integer matrix heights of ,  h e i g h t s [ r ] [ c ] heights[r][c]  represents the coordinates ( r , c ) (r, c) The height of the upper cell above sea level.

There is a lot of rain on the island. If the height of the adjacent cell is less than or equal to the height of the current cell, the rain can flow directly to the adjacent cells to the north, south, east and west. Water can flow into the ocean from any cell near the ocean.

Returns a 2D list of grid coordinates result , where  r e s u l t [ i ] = [ r i , c i ] result[i] = [r_i, c_i]  indicates that rain can be removed from the cell ( r i , c i ) (r_i, c_i) to the Pacific and Atlantic.

Example 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]]
复制代码

Example 2:

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

输出: [[0,0],[0,1],[1,0],[1,1]]
复制代码

hint:

  • m = = h e i g h t s . l e n g t h m == heights.length
  • n = = h e i g h t s [ r ] . l e n g t h n == heights[r].length
  • 1 < = m , n < = 200 1 <= m, n <= 200
  • 0 < = h e i g h t s [ r ] [ c ] < = 1 0 5 0 <= heights[r][c] <= 10^5

基本分析

整理题意,需要我们统计能够同时流向两片海域的格子。

从源点(格子)流向汇点(海域)是按照高度从高到低(非严格)的规则,那么反过来从海域到格子则是按照从低到高(非严格)规则进行,同时本身处于边缘的格子与海域联通。

因此我们可以使用两遍 DFS/BFS 进行求解:分别从与当前海域直接相连的边缘格子出发,统计能够流向当前海域的格子集合,两片海域求得的集合交集即是答案。

BFS(多源 BFS)

使用 BFS 进行求解:目的是构造出两个答案矩阵 r e s 1 res_1 r e s 2 res_2 r e s k [ i ] [ j ] = t r u e res_k[i][j] = true 代表格子 ( i , j ) (i, j) 能够流向海域,起始将所有与海域相连的格子放入队列,然后跑一遍 BFS ,所有能够进入队列的格子均能够与海域联通。

最后统计所有满足 r e s 1 [ i ] [ j ] = r e s 2 [ i ] [ j ] = t r u e res_1[i][j] = res_2[i][j] = true 的格子即是答案。

代码:

class Solution {
    int n, m;
    int[][] g;
    public List<List<Integer>> pacificAtlantic(int[][] heights) {
        g = heights;
        m = g.length; n = g[0].length;
        Deque<int[]> d1 = new ArrayDeque<>(), d2 = new ArrayDeque<>();
        boolean[][] res1 = new boolean[m][n], res2 = new boolean[m][n];
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (i == 0 || j == 0) {
                    res1[i][j] = true;
                    d1.addLast(new int[]{i, j});
                }
                if (i == m - 1 || j == n - 1) {
                    res2[i][j] = true;
                    d2.addLast(new int[]{i, j});
                }
            }
        }
        bfs(d1, res1); bfs(d2, res2);
        List<List<Integer>> ans = new ArrayList<>();
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (res1[i][j] && res2[i][j]) {
                    List<Integer> list = new ArrayList<>();
                    list.add(i); list.add(j);
                    ans.add(list);
                }
            }
        }
        return ans;
    }
    int[][] dirs = new int[][]{{1,0},{-1,0},{0,1},{0,-1}};
    void bfs(Deque<int[]> d, boolean[][] res) {
        while (!d.isEmpty()) {
            int[] info = d.pollFirst();
            int x = info[0], y = info[1], t = g[x][y];
            for (int[] di : dirs) {
                int nx = x + di[0], ny = y + di[1];
                if (nx < 0 || nx >= m || ny < 0 || ny >= n) continue;
                if (res[nx][ny] || g[nx][ny] < t) continue;
                d.addLast(new int[]{nx, ny});
                res[nx][ny] = true;
            }
        }
    }
}
复制代码
  • 时间复杂度:BFS 和统计答案的复杂度均为 O ( m n ) O(m * n) 。整体复杂度为 O ( m n ) O(m * n)
  • 空间复杂度: O ( m n ) O(m * n)

DFS

同理,使用 DFS 进行求解。

代码:

class Solution {
    int n, m;
    int[][] g;
    public List<List<Integer>> pacificAtlantic(int[][] heights) {
        g = heights;
        m = g.length; n = g[0].length;
        boolean[][] res1 = new boolean[m][n], res2 = new boolean[m][n];
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (i == 0 || j == 0) {
                    if (!res1[i][j]) dfs(i, j, res1);
                }
                if (i == m - 1 || j == n - 1) {
                    if (!res2[i][j]) dfs(i, j, res2);
                }
            }
        }
        List<List<Integer>> ans = new ArrayList<>();
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (res1[i][j] && res2[i][j]) {
                    List<Integer> list = new ArrayList<>();
                    list.add(i); list.add(j);
                    ans.add(list);
                }
            }
        }
        return ans;
    }
    int[][] dirs = new int[][]{{1,0},{-1,0},{0,1},{0,-1}};
    void dfs(int x, int y, boolean[][] res) {
        res[x][y] = true;
        for (int[] di : dirs) {
            int nx = x + di[0], ny = y + di[1];
            if (nx < 0 || nx >= m || ny < 0 || ny >= n) continue;
            if (res[nx][ny] || g[nx][ny] < g[x][y]) continue;
            dfs(nx, ny, res);
        }
    }
}
复制代码
  • 时间复杂度:DFS 和统计答案的复杂度均为 O ( m n ) O(m * n) 。整体复杂度为 O ( m n ) O(m * n)
  • 空间复杂度: O ( m n ) O(m * n)

最后

这是我们「刷穿 LeetCode」系列文章的第 No.417 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。

In this series of articles, in addition to explaining the problem-solving ideas, the most concise code will be given as much as possible. If general solutions are involved, corresponding code templates will also be provided.

In order to facilitate students to debug and submit code on the computer, I have established a related repository: github.com/SharingSour… .

In the warehouse address, you can see the link to the solution of the series of articles, the corresponding code of the series of articles, the link to the original question of LeetCode and other preferred solutions.

Guess you like

Origin juejin.im/post/7091099748098605070