Saturday, August 11, 2018

317. Shortest Distance from All Buildings

317Shortest 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 01 or 2, where:
  • Each 0 marks an empty land which you can pass by freely.
  • Each 1 marks a building which you cannot pass through.
  • Each 2 marks an obstacle which you cannot pass through.
Example:
Input: [[1,0,2,0,1],[0,0,0,0,0],[0,0,1,0,0]]

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

Output: 7 

Explanation: Given three buildings at (0,0), (0,4), (2,2), and an obstacle at (0,2),
             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.
--------------------------------------
难道在有障碍,所以最后选择了brute force, 从每一个building出发做bfs,把所有点的结果加起来找一个最小值。O(k * m * n),k为building的个数,m、n为长宽
隐藏的一个附加条件是,从最后的点必须能走到所有的building,所有额外用了一个参数来记录当前处理过的building的个数,每一次bfs都只尝试之前已经被走过的点。
class Solution {
    public int shortestDistance(int[][] grid) {
        int m = grid.length;
        int n = grid[0].length;
        
        int[][] rt = new int[m][n];
        
        int building = 1;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == 1) {
                    building--;
                    bfs(i, j, rt, grid, building);
                }
            }
        }

        return findTheShortest(rt, grid, building - 1);
    }
    
    private int findTheShortest(int[][] rt, int[][] grid, int building) {
        int shortest = Integer.MAX_VALUE;
        boolean found = false;

        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[0].length; j++) {
                if (grid[i][j] == building) {
                    shortest = Math.min(rt[i][j], shortest);
                    found = true;
                }
            }
        }
        
        return found ? shortest : -1;
    }
    
    private void bfs(int row, int col, int[][] rt, int[][] grid, int building) {
        int m = grid.length;
        int n = grid[0].length;
        boolean[][] visited = new boolean[m][n];
        Queue<Tuple> que = new LinkedList<>();
        que.add(new Tuple(row, col, 0));
        grid[row][col] = building;
        
        while (!que.isEmpty()) {
            Tuple top = que.poll();

            if (isNotValid(top, m, n, grid, visited, building)) {
                continue;
            }
            
            rt[top.row][top.col] += top.dis;
            visited[top.row][top.col] = true;
            grid[top.row][top.col] = building - 1;
            que.add(new Tuple(top.row + 1, top.col, top.dis + 1));
            que.add(new Tuple(top.row, top.col + 1, top.dis + 1));
            que.add(new Tuple(top.row - 1, top.col, top.dis + 1));
            que.add(new Tuple(top.row, top.col - 1, top.dis + 1));
        }
        
        grid[row][col] = 1;
    }
    
    private boolean isNotValid(Tuple t, int m, int n, int[][] grid, boolean[][] visited, int building) {
        int i = t.row, j = t.col;

        return i < 0 || i >= m || j < 0 || j >= n || visited[i][j] || grid[i][j] != building;
    }
}

class Tuple{
    public int row;
    public int col;
    public int dis;
    public Tuple(int row, int col, int dis) {
        this.row = row;
        this.col = col;
        this.dis = dis;
    }
}

No comments:

Post a Comment