[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 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.

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.

思路

一道典型的BFS题目,其基本思路是:对于每一个building,我们在grid上利用BFS来获取所有空白处到该建筑的距离;当所有building的结果都计算出来之后,对应位置加起来,最小值即为最优选择。朴素的代码可能需要另外开辟存储空间以及访问标记。

在下面的实现中,我们巧妙利用了grid中空白处的值0。也就是说,在对第一个建筑物求BFS的时候,我们只遍历grid[x][y] == 0的地方,一旦遍历之后,就将其值置为-1;在对第二个建筑物求BFS的时候,我们只遍历grid[x][y] == -1的地方,并且在遍历之后,就将其值置为-2,以此类推,直到所有的建筑物都被遍历。

代码

class Solution {
public:
    int shortestDistance(vector>& grid) {
        if(grid.size() == 0) {
            return 0;
        }
        int row_num = grid.size(), col_num = grid[0].size();
        int ret = 0, flag = 0;
        vector> dir{{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
        vector> count(row_num, vector(col_num, 0));
        for(int i = 0; i < row_num; ++i) {
            for(int j = 0; j < col_num; ++j) {
                if(grid[i][j] != 1) {
                    continue;
                }
                ret = INT_MAX;  // It is a bit tricky to understand why here we define ret and intiailize it as INT_MAX
                                // Each time it is first initialized as INT_MAX, and then updated as minimal summed distances
                queue> que;
                que.push(make_pair(i * col_num + j, 0));    // map 2D matrix to 1D array
                while(!que.empty()) {
                    auto val = que.front();
                    que.pop();
                    for(auto v : dir) {
                        int x = val.first / col_num + v.first;
                        int y = val.first % col_num + v.second;
                        if(x < 0 || x >= row_num || y < 0 || y >= col_num || grid[x][y] != flag) {
                            continue;
                        }
                        count[x][y] += val.second + 1;
                        --grid[x][y];
                        ret = min(ret, count[x][y]);
                        que.push(make_pair(x * col_num + y, val.second + 1));
                    }
                }
                --flag;
            }
        }
        return ret == INT_MAX ? -1 : ret;
    }
};

你可能感兴趣的:(IT公司面试习题)