Shortest Distance from All Buildings

Updated on 03 July, 2025
Shortest Distance from All Buildings header image

Problem Statement

In this scenario, you're given a grid matrix of dimensions m x n where each cell contains values 0, 1, or 2. The values represent different elements in the grid:

  • 0 marks an empty land where it's possible to build a house.
  • 1 marks a building, which is an immutable structure that you cannot move through.
  • 2 marks an obstacle, which also cannot be traversed.

The challenge is to find an empty land represented by 0 on which to build a house such that the sum of the distances from this house to all existing buildings (1s) is minimized. This sum of distances is calculated using Manhattan Distance, defined as distance(p1, p2) = |p2.x - p1.x| + |p2.y - p1.y|, implying you can only move in straight paths either horizontally or vertically.

Your goal is to return the minimum total travel distance from the house to all buildings. If it's impossible to place such a house due to the grid's layout (for instance, all buildings being surrounded by obstacles), the function should return -1.

Examples

Example 1

Input:

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

Example 2

Input:

grid = [[1,0]]

Output:

1

Example 3

Input:

grid = [[1]]

Output:

-1

Constraints

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 50
  • grid[i][j] is either 0, 1, or 2.
  • There will be at least one building in the grid.

Approach and Intuition

To solve the problem effectively, understanding the placement of buildings, empty lands, and obstacles is crucial. Given the constraints and requirements here are logical steps to derive the solution:

  1. Identifying Reachable Points: Begin by determining which empty lands are actually accessible from any building. This can be established via a Breadth-First Search (BFS) from each building to explore all neighboring cells (up, down, left, and right) until hitting an obstacle or edge of the grid.

  2. Distance Accumulation: During the BFS, for each empty land reached from a building, accumulate the total distance traveled from that building to the land. This should be repeated from every building on the grid so that at the end of this calculation, you'll have the total distance required to reach each empty land from every building.

  3. Minimum Distance Calculation: Once the distances are accumulated and stored, the next step is to determine the minimum distance from the stored values. Here, you'll iterate through each cell classified as empty land and check if it can be reached from all buildings. If yes, compare its total distance to a running minimum.

Handling Edge Cases: There are specific cases to manage such as:

  • If there’s only one building and no empty land directly adjacent, then it's impossible to place another building, hence return -1.
  • In grids with a high density of obstacles, ensure no incorrect assumptions are made about the accessibility of certain cells.

By methodically checking each potential house placement in comparison to all buildings and employing BFS for accurate distance measurements, the solution ensures both correctness and optimization in terms of placement and distance calculation.

Solutions

  • C++
cpp
class Solution {
public:
    int findMinDistance(vector<vector<int>>& matrix) {
        // Direction vectors for movement.
        int move[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
            
        int m = matrix.size();
        int n = matrix[0].size();
            
        // Matrix to accumulate distances from each building.
        vector<vector<int>> distanceSum(m, vector<int>(n, 0));
    
        int traceValue = 0;
        int shortestDist = INT_MAX;
    
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                // Run a BFS for each building found.
                if (matrix[i][j] == 1) {
                    shortestDist = INT_MAX;
                    queue<pair<int, int>> bfsQueue;
                    bfsQueue.push({i, j});
    
                    int levelSteps = 0;
    
                    while (!bfsQueue.empty()) {
                        levelSteps++;
    
                        for (int sz = bfsQueue.size(); sz > 0; --sz) {
                            auto current = bfsQueue.front();
                            bfsQueue.pop();
    
                            for (auto& dir : move) {
                                int x = current.first + dir[0];
                                int y = current.second + dir[1];
    
                                // Process only the cells with current trace value.
                                if (x >= 0 && x < m &&
                                    y >= 0 && y < n &&
                                    matrix[x][y] == traceValue) {
                                    matrix[x][y]--;
                                    distanceSum[x][y] += levelSteps;
    
                                    bfsQueue.push({x, y});
                                    shortestDist = min(shortestDist, distanceSum[x][y]);
                                }
                            }
                        }
                    }
    
                    // Adjust trace value for the next potential BFS.
                    traceValue--;
                }
            }
        }
    
        return shortestDist == INT_MAX ? -1 : shortestDist;
    }
};

The given C++ code defines a method findMinDistance in a class Solution that computes the shortest distance from all buildings in a grid. The grid is represented as a matrix where value '1' indicates a building, and '0' could potentially be an empty space.

To solve this problem, the solution uses Breadth-First Search (BFS) for each building found in the grid:

  • Initialize matrices for distance sums and a directional move array to help with navigation in the grid.
  • Use two nested loops to traverse every element of the matrix.
  • For each building (element equals 1), reset the shortest distance to a very large number and declare a BFS queue to process levels of reachable nodes.
  • Within the BFS loop, for every cell, calculate potential moves in all four directions. If the move is valid (staying within bounds and finding cells with the current trace value):
    • Decrease the matrix value to navigate through newly found empty cells in subsequent runs.
    • Increment and aggregate distances from the building to this point.
    • Push the new coordinates into the queue and update the shortest distance if necessary.
  • After processing each building, decrease the trace value ensuring only previously unvisited spaces are considered in subsequent BFS runs for next buildings.
  • Finally, return the shortest distance found. If no such distance is computed, return -1 indicating no valid path exists.

The solution effectively uses BFS for each building and handles the grid updates dynamically to accommodate multi-building scenarios, checking all potential shortest paths.

  • Java
java
class Solution {
    public int minimumDistance(int[][] grid) {
        // Directions to move in the grid.
        int movements[][] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
            
        int maxRows = grid.length;
        int maxCols = grid[0].length;
            
        // Array to accumulate total distances to all houses for each cell.
        int[][] distanceSum = new int[maxRows][maxCols];
    
        int valueEmpty = 0;
        int shortest = Integer.MAX_VALUE;
    
        for (int i = 0; i < maxRows; ++i) {
            for (int j = 0; j < maxCols; ++j) {
    
                // Initialize BFS from house position.
                if (grid[i][j] == 1) {
                    shortest = Integer.MAX_VALUE;
    
                    Queue<int[]> bfsQueue = new LinkedList<>();
                    bfsQueue.offer(new int[]{ i, j });
    
                    int levelSteps = 0;
    
                    while (!bfsQueue.isEmpty()) {
                        levelSteps++;
    
                        for (int size = bfsQueue.size(); size > 0; --size) {
                            int[] current = bfsQueue.poll();
    
                            for (int[] move : movements) {
                                int newI = current[0] + move[0];
                                int newJ = current[1] + move[1];
    
                                // Process only valid and matching empty land value cells.
                                if (newI >= 0 && newI < maxRows && newJ >= 0 && newJ < maxCols &&
                                    grid[newI][newJ] == valueEmpty) {
                                    grid[newI][newJ]--;
                                    distanceSum[newI][newJ] += levelSteps;
    
                                    bfsQueue.offer(new int[]{ newI, newJ });
                                    shortest = Math.min(shortest, distanceSum[newI][newJ]);
                                }
                            }
                        }
                    }
    
                    valueEmpty--;
                }
            }
        }
    
        return shortest == Integer.MAX_VALUE ? -1 : shortest;
    }
}

The provided Java solution addresses the problem of finding the shortest distance from all buildings on a grid. Here are the steps the code follows:

  1. Define moving directions as an array to facilitate grid traversal.
  2. Initialize the grid dimensions and a distanceSum array to track total distances to houses from each cell.
  3. Iterate through each cell in the grid.
    • If a cell is identified as a house (grid[i][j] == 1), BFS (Breadth-First Search) initializes from this cell to calculate distances to all reachable cells.
  4. Use a queue to manage the BFS process, iterating level by level to accumulate distances correctly.
  5. For each house, set the shortest variable to track the smallest accumulated distance found during BFS.
  6. Explore each possible movement using the defined direction vectors, ensuring boundaries are respected and only moving to valid cells.
  7. After distance calculations, decrement an empty value that helps to distinguish between different BFS levels and layers, ensuring that cells aren't revisited inappropriately.
  8. If no valid paths exist from some house to another part of the grid, shortest remains at its initialized maximum value and the function returns -1, indicating no valid moves were found.

The solution effectively uses BFS to explore the grid from multiple sources (houses) and updates distances to common points, calculating the minimum distance required to reach from every house to each empty land cell, efficiently handling typical challenges in multi-source shortest path problems on grids.

  • JavaScript
js
// Direction vectors for 4 directions
let directions = [[1, 0], [0, 1], [-1, 0], [0, -1]];
    
// Defining a Node class for Queue linked-list structure.
class ListNode {
    constructor(x, y) {
        this.x = x;
        this.y = y;
        this.next = null;
        this.previous = null;
    }
}
    
class SimpleQueue {
    constructor() {
        this.first = null;
        this.last = null;
        this.size = 0;
    }
    
    getSize() {
        return this.size;
    }
    
    enqueue(x, y) {
        let node = new ListNode(x, y);
        if (!this.first) {
            this.first = node;
            this.last = node;
        } else {
            this.last.next = node;
            node.previous = this.last;
            this.last = node;
        }
        this.size++;
    }
    
    dequeue() {
        if (!this.first) return null;
        let node = this.first;
        this.first = this.first.next;
        if (this.first) {
            this.first.previous = null;
        } else {
            this.last = null;
        }
        this.size--;
        return node;
    }
    
    isEmpty() {
        return this.size === 0;
    }
}
    
let findShortestDistance = function (matrix) {
    let minimumDistance = Infinity;
    let rowCount = matrix.length;
    let columnCount = matrix[0].length;
    
    // Distance matrix to accumulate distances from each house.
    let distanceMatrix = Array.from({ length: rowCount }, () => Array(columnCount).fill(0));
    
    // Start BFS from each building and decrement land value each time to ensure isolation.
    let landId = 0;
    let optimalDistance = Infinity;
    
    for (let row = 0; row < rowCount; row++) {
        for (let col = 0; col < columnCount; col++) {
            if (matrix[row][col] == 1) {
                optimalDistance = Infinity;
                let queue = new SimpleQueue();
                queue.enqueue(row, col);
                let distance = 0;
    
                while (!queue.isEmpty()) {
                    distance++;
                    let currentSize = queue.getSize();
                        
                    for (let i = 0; i < currentSize; i++) {
                        let current = queue.dequeue();
                        directions.forEach(([dx, dy]) => {
                            let nx = current.x + dx;
                            let ny = current.y + dy;
                            if (nx >= 0 && nx < rowCount && ny >= 0 && ny < columnCount && matrix[nx][ny] === landId) {
                                matrix[nx][ny]--;
                                distanceMatrix[nx][ny] += distance;
                                queue.enqueue(nx, ny);
                                optimalDistance = Math.min(optimalDistance, distanceMatrix[nx][ny]);
                            }
                        });
                    }
                }
    
                landId--;
            }
        }
    }
    
    return optimalDistance === Infinity ? -1 : optimalDistance;
};

This JavaScript solution provides functionality to compute the Shortest Distance from All Buildings on a grid, represented by a matrix. Buildings, open land, and obstacles are denoted by 1, 0, and -1 respectively in the matrix. The primary data structure utilized here is a custom queue implemented using a doubly linked list, allowing elements to be added or removed efficiently.

The solution involves several key components:

  • Direction Vectors: To facilitate four-way movement (up, down, left, right) on the grid.
  • ListNode and SimpleQueue Classes: ListNode represents an individual node in the queue, and SimpleQueue manages nodes in FIFO order, supporting operations like enqueue, dequeue, and isEmpty.
  • Core Function: findShortestDistance, which takes the grid as input and calculates the shortest path from all buildings to any open land space. This function uses Breadth-First Search (BFS) to traverse the grid and simultaneously updates a distance matrix, tracking minimum distances from each building.

Steps performed are:

  1. Initialize a distance matrix to store cumulative distances from all buildings to each point.
  2. Execute BFS starting from each building:
    • Use a decrementing landId to identify and mark cells visited in the current search, thus isolating each BFS traversal and preventing cross contamination of paths.
    • For each open land cell reached during BFS, update its distance in the distance matrix.
    • Keep track of the minimum distance encountered.

Edge cases handled:

  • Return -1 if no land is reachable from any building.

The solution ensures that the BFS traversal for each building does not interfere with others by dynamically adjusting the grid's values, made feasible through the introduction of a landId that changes with each BFS initiation. This approach efficiently computes the shortest aggregate distance while guaranteeing the isolation of each BFS traversal.

Comments

No comments yet.