LeetCode关于二维数组BFS和DFS的问题

2018-03-29  本文已影响653人  专职跑龙套

关于我的 Leetcode 题目解答,代码前往 Github:https://github.com/chenxiangcyr/leetcode-answers


LeetCode题目:317. Shortest Distance from All Buildings
You want to build a house on an empty land which reaches all buildings in the shortest amount of distance. You can only move up, down, left and right. You are given a 2D grid of values 0, 1 or 2, where:

For example, given three buildings at (0,0), (0,4), (2,2), and an obstacle at (0,2):

1 - 0 - 2 - 0 - 1
|   |   |   |   |
0 - 0 - 0 - 0 - 0
|   |   |   |   |
0 - 0 - 1 - 0 - 0

The point (1,2) is an ideal empty land to build a house, as the total travel distance of 3+3+1=7 is minimal. So return 7.

Note:
There will be at least one building. If it is not possible to build such house according to the above rules, return -1.

class Solution {
    public int shortestDistance(int[][] grid) {
        if(grid == null || grid.length == 0 || grid[0].length == 0) return -1;
        
        int row = grid.length;
        int col = grid[0].length;
        
        // record1记录每一个empty land能联通到多少个building
        int[][] record1 = new int[row][col];
        
        // record2记录每一个empty land到能够联通到的building的距离之和
        int[][] record2 = new int[row][col];
        
        // building数目
        int buildingCount = 0;
        
        for (int r = 0; r < row; r++) {
            for (int c = 0; c < col; c++) {
                // 找到每一个building,做BFS,计算其到每一个empty land的距离
                if (grid[r][c] == 1) {
                    // building数目
                    buildingCount++;
                    
                    boolean[][] visited = new boolean[row][col];
                    
                    Queue<int[]> queue = new LinkedList<int[]>();
                    queue.offer(new int[]{r, c});
                    
                    int distance = 0;
                    while (!queue.isEmpty()) {
                        int size = queue.size();
                        
                        // 按层次的BFS
                        for (int i = 0; i < size; i++) {
                            int[] node = queue.poll();
                            int x = node[0];
                            int y = node[1];
                            
                            // record1记录每一个empty land能联通到多少个building
                            record1[x][y]++;
                            
                            // record2记录每一个empty land到能够联通到的building的距离之和
                            record2[x][y]+=distance;
                            
                            int[][] dir = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
                            for(int[] d : dir) {
                                int nx = x + d[0];
                                int ny = y + d[1];
                                
                                if(nx >= 0 && nx < row && ny >= 0 && ny < col && grid[nx][ny] == 0 && !visited[nx][ny]) {
                                    queue.offer(new int[]{nx, ny});
                                    visited[nx][ny] = true;
                                }
                            }
                        }
                        
                        distance++;
                    }
                }
            }
        }
        
        int result = Integer.MAX_VALUE;
        for (int r = 0; r < row; r++) {
            for (int c = 0; c < col; c++) {
                // 遍历每一个empty land,如果它能联通到所有的building
                if (grid[r][c] == 0 && record1[r][c] == buildingCount) {
                    result = Math.min(result, record2[r][c]);
                }
            }
        }
        
        return result == Integer.MAX_VALUE ? -1 : result;
    }
}

LeetCode题目:417. Pacific Atlantic Water Flow
Given an m x n matrix of non-negative integers representing the height of each unit cell in a continent, the "Pacific ocean" touches the left and top edges of the matrix and the "Atlantic ocean" touches the right and bottom edges.

Water can only flow in four directions (up, down, left, or right) from a cell to another one with height equal or lower.

Find the list of grid coordinates where water can flow to both the Pacific and Atlantic ocean.

Note:

Example:

Given the following 5x5 matrix:
  Pacific ~   ~   ~   ~   ~ 
       ~  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  *
          *   *   *   *   * Atlantic
Return:
[[0, 4], [1, 3], [1, 4], [2, 2], [3, 0], [3, 1], [4, 0]] (positions with parentheses in above matrix).
class Solution {
    public List<int[]> pacificAtlantic(int[][] matrix) {
        
        List<int[]> result = new ArrayList<int[]>();
        
        if(matrix == null || matrix.length == 0 || matrix[0].length == 0) return result;
        
        int m = matrix.length;
        int n = matrix[0].length;
        
        // pacific[i][j]表示(i, j)能否得到pacific
        boolean[][] pacific = new boolean[m][n];
        // atlantic[i][j]表示(i, j)能否得到atlantic
        boolean[][] atlantic = new boolean[m][n];
        
        for (int i = 0; i < m; i++) {
            // 从左边开始搜索是否可以到达pacific
            dfs(matrix, pacific, i, 0, m, n);
            
            // 从右边开始搜索是否可以到达atlantic
            dfs(matrix, atlantic, i, n - 1, m, n);
        }
        
        for (int i = 0; i < n; i++) {
            // 从上边开始搜索是否可以到达pacific
            dfs(matrix, pacific, 0, i, m, n);
            
            // 从下边开始搜索是否可以到达atlantic
            dfs(matrix, atlantic, m - 1, i, m, n);
        }
        
        for(int i = 0; i < m; i++) {
            for(int j = 0; j < n; j++) {
                if(pacific[i][j] == true && atlantic[i][j] == true) {
                    result.add(new int[]{i, j});
                }
            }
        }
        
        return result;
    }
    
    public void dfs(int[][] matrix, boolean[][] canArrive, int x, int y, int m, int n) {
        // canArrive也起到了visited数组的作用
        canArrive[x][y] = true;
        
        int[] directionX = new int[]{-1, 1, 0, 0};
        int[] directionY = new int[]{0, 0, -1, 1};
        
        // 遍历4个方向
        for(int i = 0; i < 4; i++) {
            int newX = x + directionX[i];
            int newY = y + directionY[i];
            
            if(newX >= 0 && newX < m && newY >= 0 && newY < n 
               && !canArrive[newX][newY] 
               && matrix[newX][newY] >= matrix[x][y]) {
                dfs(matrix, canArrive, newX, newY, m, n);
            }
        }
    }
}
上一篇 下一篇

猜你喜欢

热点阅读