• [LintCode] Nearest Exit


    You are given a m x n 2D grid initialized with these three possible values.

    -1 - A wall or an obstacle.
    0 - A gate.
    INF - Infinity means an empty room. We use the value 2^31 - 1 = 2147483647 to represent INF as you may assume that the distance to a gate is less than 2147483647.
    Fill each empty room with the distance to its nearest gate. If it is impossible to reach a gate, it should be filled with INF.

    Example

    Given the 2D grid:

    INF  -1  0  INF
    INF INF INF  -1
    INF  -1 INF  -1
      0  -1 INF INF
    

    return the result:

      3  -1   0   1
      2   2   1  -1
      1  -1   2  -1
      0  -1   3   4

    Solution 1. O(m^2 * n^2) runtime, O(n * m) space 

    A straightforward way of solving this problem is to perform a bfs on all empty rooms(cell of value INF). 

    Take each empty room as the source point of level 0 and use a distance variable to keep track of the current traversal level.

    If at certain level, a gate cell is first found, set the distance of the current source empty room to the nearest exit as the current distance value.

    The runtime of this algorithm is O(n * m) * O(n * m) as there are n * m possible source points and each bfs takes O(n * m) time, 

    The space usage is O(n * m) as we need to keep track of which cells have been visited so that they'll not be visited again. 

    One note here: since this is the a multiple source problem and this algorithm changes its distance value one at a time. Extra care should be given 

    to make sure a previous bfs result does not affect the correctness of the next bfs. 

    If highlighted line 42 is changed to rooms[x][y] == Integer.MAX_VALUE, this algorithm will be incorrect. This is because a previous bfs may already 

    change one of the empty cell value from INF to some distance value. In the current bfs of the current source point, it should still be able to pass through

    the previously changed empty cell even if its value is not INF anymore. So the check condition should be rooms[x][y] != - 1. As long as the neighboring cell

    has not been visited before and it is not a wall, the algorithm should add it to the queue for future traversal.

     1 public class Solution {
     2     class Point {
     3         int row;
     4         int col;
     5         Point(int r, int c) {
     6             this.row = r;
     7             this.col = c;
     8         }
     9     }
    10     private int[] deltaX = {-1, 0, 1, 0};
    11     private int[] deltaY = {0, 1, 0, -1};
    12     public void wallsAndGates(int[][] rooms) {
    13         if(rooms == null || rooms.length == 0 || rooms[0].length == 0) {
    14             return;
    15         }
    16         for(int r = 0; r < rooms.length; r++) {
    17             for(int c = 0; c < rooms[0].length; c++) {
    18                 if(rooms[r][c] == Integer.MAX_VALUE) {
    19                     bfs(rooms, r, c);
    20                 }
    21             }
    22         }
    23     }
    24     private void bfs(int[][] rooms, int row, int col) {
    25         Queue<Point> queue = new LinkedList<Point>();
    26         boolean[][] visited = new boolean[rooms.length][rooms[0].length];
    27         queue.add(new Point(row, col));
    28         visited[row][col] = true;
    29         int distance = 1;
    30         
    31         while(!queue.isEmpty()) {
    32             int size = queue.size();
    33             for(int i = 0; i < size; i++) {
    34                 Point currPoint = queue.poll();    
    35                 for(int dir = 0; dir < 4; dir++) {
    36                     int x = currPoint.row + deltaX[dir]; int y = currPoint.col + deltaY[dir];
    37                     if(isInBound(rooms, x, y) && !visited[x][y]) {
    38                         if(rooms[x][y] == 0) {
    39                             rooms[row][col] = distance;
    40                             return;
    41                         }
    42                         else if(rooms[x][y] != -1){
    43                             queue.add(new Point(x, y));
    44                             visited[x][y] = true;
    45                         }
    46                     }                    
    47                 }
    48             }
    49             distance++;
    50         }
    51     }
    52     private boolean isInBound(int[][] rooms, int row, int col) {
    53         return (row >= 0 && row < rooms.length) && (col >= 0 && col < rooms[0].length);
    54     }
    55 }
    
    

    Solution 2.  O(n * m) runtime, O(n * m) space

    If there is only one gate, then the problem is a multiple sources single destination problem. Since the distance from an empty room to a gate 

    is the same with the distance from the same gate to the same empty room. We can convert it to a single source multiple destinations problem:

    Find all the shortest distances from one single gate to all the empty rooms. Since the distance is measured in unit cell distance, we can use 

    BFS to solve this problem in O(n * m) time.

    The original problem can have multiple gates, which is a multiple sources multiple destinations problem. 

    We can treate all the gates as one big source, and start the bfs at the same time from this big source(start bfs from all gates at the same time).

    If any gate in this big source reaches an empty room first, the shortest distance from an empty room to any gate is established. Later traversals 

    on the same empty room from other gates are simply ignored as there is already a shorter path from this empty room to another gate. All other 

    unvisited empty rooms that can be connected with the current empty room can acheive a shorter distance to a gate by using the current empty room's 

    shortest path to a gate.

     1 public class Solution {
     2     class Point {
     3         int row;
     4         int col;
     5         Point(int r, int c) {
     6             this.row = r;
     7             this.col = c;
     8         }
     9     }
    10     public void wallsAndGates(int[][] rooms) {
    11         if(rooms == null || rooms.length == 0 || rooms[0].length == 0) {
    12             return;
    13         }
    14         int n = rooms.length;
    15         int m = rooms[0].length;
    16         int[] deltaX = {-1, 0, 1, 0};
    17         int[] deltaY = {0, 1, 0, -1};
    18         Queue<Point> queue = new LinkedList<Point>();
    19         for(int i = 0; i < n; i++) {
    20             for(int j = 0; j < m; j++) {
    21                 if(rooms[i][j] == 0) {
    22                     queue.add(new Point(i, j));
    23                 }
    24             }
    25         }
    26         while(!queue.isEmpty()) {
    27             Point currPoint = queue.poll();
    28             for(int dir = 0; dir < 4; dir++) {
    29                 int x = currPoint.row + deltaX[dir];
    30                 int y = currPoint.col + deltaY[dir];
    31                 if(isInBound(rooms, x, y)) {
    32                     if(rooms[x][y] == Integer.MAX_VALUE) {
    33                         rooms[x][y] = rooms[currPoint.row][currPoint.col] + 1;    
    34                         queue.add(new Point(x, y)); 
    35                     }
    36                 }
    37             }
    38         }
    39     }
    40     private boolean isInBound(int[][] rooms, int row, int col) {
    41         return (row >= 0 && row < rooms.length && col >= 0 && col < rooms[0].length);
    42     }
    43 }
     

    Related Problems 

    Number of Islands

    Surrounded Regions 

    Build Post Office 

    Build Post Office II




  • 相关阅读:
    clearfix 清除浮动的问题
    python第四十五课——继承性之多继承
    Linux基础第六课——grep|awk|sort|uniq
    Linux基础第五课——用户管理
    Linux基础第四课——文件操作
    Linux第三课——目录操作
    Linux基础第二课——系统架构
    Linux基础第一课——基础知识了解
    01 http协议概念及工作流程
    18- php Redis扩展编译
  • 原文地址:https://www.cnblogs.com/lz87/p/7493966.html
Copyright © 2020-2023  润新知