Shortest Distance After Road Addition Queries I solution and explanation
9 more videos on this problem
Shortest Distance After Road Addition Queries I | Easy Explanation | Leetcode 3243 |codestorywithMIKcodestorywithMIK · 25:20 · 7K views
Shortest Distance After Road Addition Queries I | Leetcode 3243Techdose · 14:07 · 2K views
SHORTEST DISTANCE AFTER ROAD ADDITION QUERIES | LEETCODE 3243 | PYTHON GRAPH SOLUTIONCracking FAANG · 11:53 · 1K views
LeetCode 3243 Shortest Distance After Road Addition Queries I | Graph | Build Recursive Thinking 🔥Code Harmony · 20:23 · 224 views
3243. Shortest Distance After Road Addition Queries I | Daily Challenge | 27 Nov 2024 | POTDCTO Bhaiya · 27:35 · 190 views
LeetCode 3243 - Shortest Distance After Road Addition Queries I - JavaAlpha-Code · 8:43 · 83 views
Concept - Breadth-First-Seach. LeetCode 3243. Shortest Distance After Road Addition Queries I.CS-Reference · 18:57 · 68 views
LeetCode 3243 .- Shortest Distance After Road Addition Queries I (Typescript Solution)An Average Programmer · 6:35 · 66 views
LEETCODE #3243 | SHORTEST DISTANCE AFTER ROAD ADDITION QUERIES 1 -- problem solvedKubeDynamic · 5:14 · 57 views
Shortest Distance After Road Addition Queries I | Leetcode 3243 | Java Code | Developer CoderDeveloper Coder · 22:48 · 51 views
The problem
You are given an integer n and a 2D integer array queries.
There are n cities numbered from 0 to n - 1. Initially, there is a unidirectional road from city i to city i + 1 for all 0 <= i < n - 1.
queries[i] = [ui, vi] represents the addition of a new unidirectional road from city ui to city vi. After each query, you need to find the length of the shortest path from city 0 to city n - 1.
Return an array answer where for each i in the range [0, queries.length - 1], answer[i] is the length of the shortest path from city 0 to city n - 1 after processing the first i + 1 queries.
Example 1:
Input: n = 5, queries = [[2,4],[0,2],[0,4]]
Output: [3,2,1]
Explanation:

After the addition of the road from 2 to 4, the length of the shortest path from 0 to 4 is 3.

After the addition of the road from 0 to 2, the length of the shortest path from 0 to 4 is 2.

After the addition of the road from 0 to 4, the length of the shortest path from 0 to 4 is 1.
Example 2:
Input: n = 4, queries = [[0,3],[0,2]]
Output: [1,1]
Explanation:

After the addition of the road from 0 to 3, the length of the shortest path from 0 to 3 is 1.

After the addition of the road from 0 to 2, the length of the shortest path remains 1.
Constraints:
3 <= n <= 5001 <= queries.length <= 500queries[i].length == 20 <= queries[i][0] < queries[i][1] < n1 < queries[i][1] - queries[i][0]- There are no repeated roads among the queries.
Approach overview
Problem Overview: You start with n cities connected in a straight line where each city i has a road to i+1. Queries add new directed roads between cities. After each addition, compute the shortest distance from city 0 to city n-1.
Approach 1: Breadth-First Search (BFS) Recompute per Query (Time: O(q*(n+e)), Space: O(n+e))
Maintain an adjacency list representing the current graph. Initially add edges i → i+1 for all cities. For every query (u, v), append the new edge to the adjacency list and run a Breadth-First Search starting from node 0. Since all roads have equal weight, BFS naturally finds the shortest number of edges to each city. The first time you reach n-1 gives the shortest path length. This approach is straightforward and works well because constraints keep the graph relatively small. Each query triggers a fresh traversal of the graph.
Approach 2: Dijkstra with Priority Queue (Time: O(q*(n+e) log n), Space: O(n+e))
Another option is running Dijkstra's Algorithm after each road insertion. Store the graph in an adjacency list and use a min-heap to always expand the node with the smallest current distance. Although all edges have weight 1 (making BFS slightly more efficient), Dijkstra provides a general solution for shortest paths and works even if weights change in future variations. After each query, push the start node 0 into the priority queue and relax edges until reaching n-1. The priority queue ensures nodes are processed in increasing distance order.
Recommended for interviews: BFS is typically expected because every road has equal weight. Running BFS after each query demonstrates understanding of shortest paths in unweighted graphs and keeps implementation simple. Mentioning the Dijkstra alternative shows awareness of weighted graph techniques and broader problem-solving skills.
Approach 1: Breadth-First Search (BFS) Approach
This approach treats the problem as a graph traversal problem where each city is a node and roads are directed edges. Initially, the graph is linear, and each query introduces a single directed edge. We can use BFS to update and find the shortest path after each new road is added, recalculating the shortest path from node 0 to node n-1.
from collections import deque
def shortest_path(n, queries):
# Initialize graph with the default path 0 -> 1 -> ... -> n-1
graph = {i: [i + 1] for i in range(n - 1)}
graph[n-1] = []
def bfs_distance(start, end):
visited = [False] * n
queue = deque([(start, 0)])
visited[start] = True
while queue:
node, dist = queue.popleft()
if node == end:
return dist
for neighbor in graph[node]:
if not visited[neighbor]:
visited[neighbor] = True
queue.append((neighbor, dist + 1))
return -1 # If unreachable (should not happen)
answers = []
for u, v in queries:
graph[u].append(v)
answers.append(bfs_distance(0, n - 1))
return answers
# Example usage
n = 5
queries = [[2, 4], [0, 2], [0, 4]]
print(shortest_path(n, queries))function shortestPath(n, queries) {
const graph = Array.from({ length: n }, () => []);
for (let i = 0; i < n - 1; ++i) {
graph[i].push(i + 1);
}
function bfsDistance(start, end) {
let queue = [{ node: start, dist: 0 }];
let visited = Array(n).fill(false);
visited[start] = true;
for (let position = 0; position < queue.length; position++) {
const { node, dist } = queue[position];
if (node === end) return dist;
for (const neighbor of graph[node]) {
if (!visited[neighbor]) {
visited[neighbor] = true;
queue.push({ node: neighbor, dist: dist + 1 });
}
}
}
return -1;
}
let results = [];
for (const [u, v] of queries) {
graph[u].push(v);
results.push(bfsDistance(0, n - 1));
}
return results;
}
// Example usage
const n = 5;
const queries = [[2, 4], [0, 2], [0, 4]];
console.log(shortestPath(n, queries));This Python function shortest_path accepts the number of cities, n, and the list of queries that represent new road additions. The function maintains a dynamic graph representation and repeatedly performs BFS to determine the new shortest path from city 0 to city n-1 after each query.
Time Complexity: O(n * q), where n is the number of cities and q is the number of queries, due to the BFS traversal for each query.
Space Complexity: O(n + q), accounting for graph representation and BFS queue.
Approach 2: Dijkstra's Algorithm with Priority Queue
This approach models the problem as a weighted graph and uses Dijkstra's algorithm, which is suitable since the graph predominantly has unit weights. This algorithm efficiently finds the shortest path from the start city to the end city after each new road is introduced, leveraging a priority queue to always expand the shortest known total distance path.
import java.util.*;
public class ShortestPath {
public static List<Integer> shortestPath(int n, List<int[]> queries) {
List<List<int[]>> graph = new ArrayList<>();
for (int i = 0; i < n; i++) {
graph.add(new ArrayList<>());
if (i < n - 1) {
graph.get(i).add(new int[]{i + 1, 1});
}
}
List<Integer> results = new ArrayList<>();
for (int[] query : queries) {
int u = query[0], v = query[1];
graph.get(u).add(new int[]{v, 1});
results.add(dijkstra(n, graph));
}
return results;
}
private static int dijkstra(int n, List<List<int[]>> graph) {
PriorityQueue<int[]> pq = new PriorityQueue<>(Comparator.comparingInt(a -> a[1]));
int[] dist = new int[n];
Arrays.fill(dist, Integer.MAX_VALUE);
dist[0] = 0;
pq.offer(new int[]{0, 0});
while (!pq.isEmpty()) {
int[] current = pq.poll();
int u = current[0], d = current[1];
if (d > dist[u]) continue;
for (int[] edge : graph.get(u)) {
int v = edge[0], weight = edge[1];
if (d + weight < dist[v]) {
dist[v] = d + weight;
pq.offer(new int[]{v, dist[v]});
}
}
}
return dist[n - 1];
}
public static void main(String[] args) {
int n = 5;
List<int[]> queries = Arrays.asList(new int[]{2, 4}, new int[]{0, 2}, new int[]{0, 4});
System.out.println(shortestPath(n, queries));
}
}#include <iostream>
#include <vector>
#include <queue>
#include <climits>
using namespace std;
vector<int> shortestPath(int n, vector<pair<int, int>>& queries) {
vector<vector<pair<int, int>>> graph(n);
for (int i = 0; i < n - 1; ++i) {
graph[i].emplace_back(i + 1, 1);
}
auto dijkstra = [&](int target) {
vector<int> dist(n, INT_MAX);
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
dist[0] = 0;
pq.emplace(0, 0);
while (!pq.empty()) {
auto [d, u] = pq.top();
pq.pop();
if (d > dist[u]) continue;
for (auto& [v, weight] : graph[u]) {
if (dist[u] + weight < dist[v]) {
dist[v] = dist[u] + weight;
pq.emplace(dist[v], v);
}
}
}
return dist[target];
};
vector<int> results;
for (auto& [u, v] : queries) {
graph[u].emplace_back(v, 1);
results.push_back(dijkstra(n - 1));
}
return results;
}
int main() {
int n = 5;
vector<pair<int, int>> queries = {{2, 4}, {0, 2}, {0, 4}};
vector<int> answer = shortestPath(n, queries);
for (int res : answer) {
cout << res << " ";
}
return 0;
}In this Java solution, Dijkstra’s algorithm is implemented using a priority queue for efficiency. Each city is represented as a node and each query creates an additional edge in the graph. The code calculates the shortest path from node 0 to node n-1 after each query.
Time Complexity: O((n + q) log n), primarily due to Dijkstra's algorithm operations with the priority queue.
Space Complexity: O(n + q), needed for graph storage and priority queue usage.
Approach 3: BFS
We first build a directed graph g, where g[i] represents the list of cities that can be reached from city i. Initially, each city i has a one-way road to city i + 1.
Then, for each query [u, v], we add v to the list of reachable cities from u, and then use BFS to find the shortest path length from city 0 to city n - 1, adding the result to the answer array.
Finally, we return the answer array.
The time complexity is O(q times (n + q)), and the space complexity is O(n + q). Here, n and q are the number of cities and the number of queries, respectively.
function shortestDistanceAfterQueries(n: number, queries: number[][]): number[] {
const g: number[][] = Array.from({ length: n }, () => []);
for (let i = 0; i < n - 1; ++i) {
g[i].push(i + 1);
}
const bfs = (i: number): number => {
const q: number[] = [i];
const vis: boolean[] = Array(n).fill(false);
vis[i] = true;
for (let d = 0; ; ++d) {
const nq: number[] = [];
for (const u of q) {
if (u === n - 1) {
return d;
}
for (const v of g[u]) {
if (!vis[v]) {
vis[v] = true;
nq.push(v);
}
}
}
q.splice(0, q.length, ...nq);
}
};
const ans: number[] = [];
for (const [u, v] of queries) {
g[u].push(v);
ans.push(bfs(0));
}
return ans;
}func shortestDistanceAfterQueries(n int, queries [][]int) []int {
g := make([][]int, n)
for i := range g {
g[i] = append(g[i], i+1)
}
bfs := func(i int) int {
q := []int{i}
vis := make([]bool, n)
vis[i] = true
for d := 0; ; d++ {
for k := len(q); k > 0; k-- {
u := q[0]
if u == n-1 {
return d
}
q = q[1:]
for _, v := range g[u] {
if !vis[v] {
vis[v] = true
q = append(q, v)
}
}
}
}
}
ans := make([]int, len(queries))
for i, q := range queries {
g[q[0]] = append(g[q[0]], q[1])
ans[i] = bfs(0)
}
return ans
}Complexity comparison
| Approach | Complexity |
|---|---|
| Breadth-First Search (BFS) Approach | Time Complexity: O(n * q), where n is the number of cities and q is the number of queries, due to the BFS traversal for each query. |
| Dijkstra's Algorithm with Priority Queue | Time Complexity: O((n + q) log n), primarily due to Dijkstra's algorithm operations with the priority queue. |
| BFS | – |
Complexity analysis
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Breadth-First Search per Query | O(q*(n+e)) | O(n+e) | Best for unweighted graphs where each road has equal cost |
| Dijkstra with Priority Queue | O(q*(n+e) log n) | O(n+e) | General shortest-path solution or when edge weights vary |
Frequently asked questions
Is Shortest Distance After Road Addition Queries I easy or hard?
The problem is rated Medium on LeetCode with an acceptance rate around 61%. The main challenge is recognizing that the graph changes after each query and recomputing the shortest path efficiently using BFS or Dijkstra.
Shortest Distance After Road Addition Queries I Python/Java solution
Python and JavaScript implementations typically use BFS with a queue because the graph is unweighted. C++ and Java solutions sometimes demonstrate Dijkstra with a priority queue. Both approaches compute the shortest path from node 0 to node n-1 after each query.
How to solve Shortest Distance After Road Addition Queries I efficiently?
Maintain an adjacency list of the graph and append the new road for every query. After inserting the edge, run BFS from node 0 to compute the distance to node n-1. Because all edges have weight 1, BFS guarantees the optimal path length without needing a priority queue.
What is the best approach for Shortest Distance After Road Addition Queries I?
Breadth-First Search (BFS) after each query is the most practical solution. Since every road has weight 1, BFS naturally finds the shortest number of edges from city 0 to city n-1. Each query adds one edge to the graph, then a BFS traversal computes the updated shortest path.
Is Shortest Distance After Road Addition Queries I asked at Google/Amazon/Meta?
Graph traversal and shortest path problems are common in interviews at companies like Google, Amazon, and Meta. Variations involving BFS, dynamic edge updates, or shortest path recomputation frequently appear in online assessments and technical rounds.
What data structure is used in Shortest Distance After Road Addition Queries I?
The solution relies on an adjacency list to represent the graph and a queue for BFS traversal. If using Dijkstra, a priority queue (min-heap) is also required. Arrays or lists track visited nodes and current distances.
What is the time complexity of Shortest Distance After Road Addition Queries I?
The BFS approach runs in O(q*(n+e)) time where q is the number of queries, n is the number of cities, and e is the number of roads currently in the graph. Each query triggers a full BFS traversal. Space complexity is O(n+e) for storing the adjacency list and visited structures.
