Talentd
FleetCode
Make and follow sheets.Sign in

Minimum Cost of a Path With Special Roads solution and explanation

MediumArrayGraphHeap (Priority Queue)Shortest Path9 min read43.3% acceptanceUpdated 9 Apr 2026
花花酱 LeetCode 2662. Minimum Cost of a Path With Special Roads - 刷题找工作 EP411Hua Hua · 16:47 · 3K viewsWatch on YouTube
8 more videos on this problem
  1. 花花酱 LeetCode 2662. Minimum Cost of a Path With Special Roads - 刷题找工作 EP411Hua Hua · 16:47 · 3K views
  2. Leetcode 2662 Minimum Cost of a Path With Special Roads HindiThinkCode · 15:13 · 2K views
  3. Leetcode Weekly contest 343 - Medium - Minimum Cost of a Path With Special RoadsPrakhar Agrawal · 15:00 · 2K views
  4. 2662. Minimum Cost of a Path With Special Roads (Leetcode Medium)Programming Live with Larry · 12:59 · 1K views
  5. Leetcode 2662. Minimum Cost of a Path With Special Roads | Weekly Contest 343 | Leetcode weeklyOffCampus Phodenge | Aman Chowdhury · 34:36 · 1K views
  6. 【每日一题】LeetCode 2662. Minimum Cost of a Path With Special RoadsHuifeng Guan · 29:14 · 647 views
  7. Leetcode 2662 Minimum Cost of a Path With Special Roads - BFS Approach ExplainedAlgorithmicIQ · 28:27 · 597 views
  8. [Eng] Leetcode Weekly Contest 343 | 2662. Minimum Cost of a Path With Special RoadsCyCode · 7:13 · 349 views
  9. LeetCode Medium 2662 Minimum Cost Path with Special Roads Explained 🚀with Dijkstra's Algorithm🧩Talent Navigator · 11:48 · 22 views

The problem

You are given an array start where start = [startX, startY] represents your initial position (startX, startY) in a 2D space. You are also given the array target where target = [targetX, targetY] represents your target position (targetX, targetY).

The cost of going from a position (x1, y1) to any other position in the space (x2, y2) is |x2 - x1| + |y2 - y1|.

There are also some special roads. You are given a 2D array specialRoads where specialRoads[i] = [x1i, y1i, x2i, y2i, costi] indicates that the ith special road goes in one direction from (x1i, y1i) to (x2i, y2i) with a cost equal to costi. You can use each special road any number of times.

Return the minimum cost required to go from (startX, startY) to (targetX, targetY).

Example 1:

Input: start = [1,1], target = [4,5], specialRoads = [[1,2,3,3,2],[3,4,4,5,1]]

Output: 5

Explanation:

  1. (1,1) to (1,2) with a cost of |1 - 1| + |2 - 1| = 1.
  2. (1,2) to (3,3). Use specialRoads[0] with the cost 2.
  3. (3,3) to (3,4) with a cost of |3 - 3| + |4 - 3| = 1.
  4. (3,4) to (4,5). Use specialRoads[1] with the cost 1.

So the total cost is 1 + 2 + 1 + 1 = 5.

Example 2:

Input: start = [3,2], target = [5,7], specialRoads = [[5,7,3,2,1],[3,2,3,4,4],[3,3,5,5,5],[3,4,5,6,6]]

Output: 7

Explanation:

It is optimal not to use any special edges and go directly from the starting to the ending position with a cost |5 - 3| + |7 - 2| = 7.

Note that the specialRoads[0] is directed from (5,7) to (3,2).

Example 3:

Input: start = [1,1], target = [10,4], specialRoads = [[4,2,1,1,3],[1,2,7,4,4],[10,3,6,1,2],[6,1,1,2,3]]

Output: 8

Explanation:

  1. (1,1) to (1,2) with a cost of |1 - 1| + |2 - 1| = 1.
  2. (1,2) to (7,4). Use specialRoads[1] with the cost 4.
  3. (7,4) to (10,4) with a cost of |10 - 7| + |4 - 4| = 3.

Constraints:

  • start.length == target.length == 2
  • 1 <= startX <= targetX <= 105
  • 1 <= startY <= targetY <= 105
  • 1 <= specialRoads.length <= 200
  • specialRoads[i].length == 5
  • startX <= x1i, x2i <= targetX
  • startY <= y1i, y2i <= targetY
  • 1 <= costi <= 105

Approach overview

Problem Overview: You start at a coordinate on a 2D grid and need the minimum cost to reach a target. Moving normally costs the Manhattan distance between points, but some special roads let you travel between two coordinates with a custom cost. The goal is to combine normal movement and special roads to minimize total travel cost.

Approach 1: Dijkstra's Algorithm (O(n log n) time, O(n) space)

Treat the problem as a graph shortest path problem. Each relevant coordinate becomes a node: the start position and the start/end points of every special road. From any node, you can move to another coordinate using Manhattan distance, or take a special road with its given cost. Use Dijkstra’s algorithm with a heap (priority queue) to always expand the currently cheapest reachable position. The key insight is that you do not need to explore every grid cell—only the special road endpoints. Each relaxation step compares the cost of normal movement versus the cost of using a special road. This approach efficiently computes the optimal route while avoiding the huge state space of the entire grid.

Approach 2: Bellman-Ford Algorithm (O(n^2) time, O(n) space)

Model the same coordinate set as a weighted graph and run the shortest path relaxation process using Bellman-Ford. Initialize the distance to each special road endpoint as the Manhattan distance from the start. Then repeatedly relax all edges: traveling normally between endpoints or taking a special road edge. After enough iterations, the distances converge to the minimum possible costs. Bellman-Ford works well because edge weights can be arbitrary but remain non-negative in this problem. The downside is performance—every iteration scans all edges, which increases runtime compared to Dijkstra’s priority-driven exploration.

Recommended for interviews: Dijkstra’s algorithm is the expected solution. It shows you recognize the hidden graph structure and can combine Manhattan distance with weighted edges efficiently. Bellman-Ford demonstrates understanding of general shortest-path relaxation but is rarely chosen unless negative edges exist. Interviewers usually want to see the priority queue–based optimization.

Approach 1: Approach 1: Dijkstra's Algorithm

This approach uses Dijkstra's Algorithm, which is suitable for finding the shortest path in a graph with non-negative weights. Consider each unique position as a node, with bi-directional edges between any two nodes representing the cost to travel between them, either directly or through special roads.

Start at the initial position and explore the reachable positions using both direct Manhattan distance and special roads. Maintain a priority queue (min-heap) to always extend the least costly path available. The algorithm terminates when the target position is reached with the minimum cost.

import heapq

def minimumCost(start, target, specialRoads):
    startX, startY = start
    targetX, targetY = target
    # min-heap (priority queue)
    heap = [(0, startX, startY)]
    visited = set()
    while heap:
        cost, x, y = heapq.heappop(heap)
        # Check if we reached the target
        if (x, y) == (targetX, targetY):
            return cost
        if (x, y) in visited:
            continue
        visited.add((x, y))
        # Consider using special roads
        for x1, y1, x2, y2, roadCost in specialRoads:
            if (x, y) == (x1, y1) and (x2, y2) not in visited:
                heapq.heappush(heap, (cost + roadCost, x2, y2))
        # Consider moving directly to the target
        directCost = abs(targetX - x) + abs(targetY - y)
        heapq.heappush(heap, (cost + directCost, targetX, targetY))
function minimumCost(start, target, specialRoads) {
    let [startX, startY] = start;
    let [targetX, targetY] = target;
    const pq = new MinPriorityQueue({ priority: (x) => x[0] });
    pq.enqueue([0, startX, startY]);
    const visited = new Set();

    while (!pq.isEmpty()) {
        const [cost, x, y] = pq.dequeue().element;
        if (x === targetX && y === targetY) return cost;
        if (visited.has(`${x},${y}`)) continue;
        visited.add(`${x},${y}`);

        for (const [x1, y1, x2, y2, roadCost] of specialRoads) {
            if (x === x1 && y === y1 && !visited.has(`${x2},${y2}`)) {
                pq.enqueue([cost + roadCost, x2, y2]);
            }
        }
        // Push the target as final destination which simulates direct moving
        pq.enqueue([cost + Math.abs(targetX - x) + Math.abs(targetY - y), targetX, targetY]);
    }
}

This solution initializes a priority queue with the starting position at cost zero and iterates through all paths, either direct or via special roads, continuously extending the shortest available path. Once it dequeues the target position from the queue, the accumulated cost is the answer.

Complexity

Time Complexity: O((N + M) * log(N + M)), where N is the number of special roads, and M is the number of possible positions considered.
Space Complexity: O(N + M), due to the priority queue and visited set.

Try this approach in the editor

Approach 2: Approach 2: Bellman-Ford Algorithm

The Bellman-Ford algorithm is another valid approach for solving the shortest path problem in a graph with directional edges and no negative weight cycles. Unlike Dijkstra's, this approach systematically updates all paths for a given number of iterations, ensuring the shortest path puts special roads and direct routes on equal footing.

We'll iterate over each node and relax edges associated with both direct movement and special roads. Given the scope of this problem, Bellman-Ford is computationally heavier but provides valuable comparative insights.

import java.util.*;

public class Solution {
    public int minimumCost(int[] start, int[] target, int[][] specialRoads) {
        int startX = start[0], startY = start[1], targetX = target[0], targetY = target[1];
        List<int[]> edges = new ArrayList<>();
        // Add direct path edge
        edges.add(new int[]{startX, startY, targetX, targetY, Math.abs(targetX - startX) + Math.abs(targetY - startY)});
        for (int[] road : specialRoads) {
            edges.add(road);
        }
        int dist = Integer.MAX_VALUE;
        for (int i = 0; i < edges.size(); ++i) {
            boolean changed = false;
            for (int[] road : edges) {
                int x1 = road[0], y1 = road[1], x2 = road[2], y2 = road[3], cost = road[4];
                if (Math.abs(targetX - x2) + Math.abs(targetY - y2) < dist) {
                    dist = Math.min(dist, cost);
                    changed = true;
                }
            }
            if (!changed) break;
        }
        return dist;
    }
}
#include <vector>
#include <cmath>
#include <climits>
using namespace std;

int minimumCost(vector<int>& start, vector<int>& target, vector<vector<int>>& specialRoads) {
    int startX = start[0], startY = start[1], targetX = target[0], targetY = target[1];
    vector<vector<int>> edges;
    // Add direct path from start to target
    edges.push_back({startX, startY, targetX, targetY, abs(targetX - startX) + abs(targetY - startY)});
    for (auto& road : specialRoads) {
        edges.push_back(road);
    }
    int dist = INT_MAX;
    for (int i = 0; i < edges.size(); ++i) {
        int changed = false;
        for (auto& edge : edges) {
            int x1 = edge[0], y1 = edge[1], x2 = edge[2], y2 = edge[3], cost = edge[4];
            if (abs(targetX - x2) + abs(targetY - y2) < dist) {
                dist = cost;
                changed = true;
            }
        }
        if (!changed) break;
    }
    return dist;
}

This Java-based solution mirrors the Bellman-Ford algorithm, building a list of all available edges corresponding to direct and special routes. Iteratively, edge relaxation applies adjustments to the shortest paths possible, coalescing around the minimum cost eventually attained at the target location.

Complexity

Time Complexity: O(N * M), relying heavily on re-evaluating each edge relative to every node assessed.
Space Complexity: O(N), arising from the array representation of edges and storage required for managing distances.

Try this approach in the editor

Approach 3: Dijkstra

We can find that for each coordinate (x, y) we visit, suppose the minimum cost from the start point to (x, y) is d. If we choose to move directly to (targetX, targetY), then the total cost is d + |x - targetX| + |y - targetY|. If we choose to go through a special path (x_1, y_1) \rightarrow (x_2, y_2), then we need to spend |x - x_1| + |y - y_1| + cost to move from (x, y) to (x_2, y_2).

Therefore, we can use Dijkstra algorithm to find the minimum cost from the start point to all points, and then choose the smallest one from them.

We define a priority queue q, each element in the queue is a triple (d, x, y), which means that the minimum cost from the start point to (x, y) is d. Initially, we add (0, startX, startY) to the queue.

In each step, we take out the first element (d, x, y) in the queue, at this time we can update the answer, that is ans = min(ans, d + dist(x, y, targetX, targetY)). Then we enumerate all special paths (x_1, y_1) \rightarrow (x_2, y_2) and add (d + dist(x, y, x_1, y_1) + cost, x_2, y_2) to the queue.

Finally, when the queue is empty, we can get the answer.

The time complexity is O(n^2 times log n), and the space complexity is O(n^2). Where n is the number of special paths.

function minimumCost(start: number[], target: number[], specialRoads: number[][]): number {
    const dist = (x1: number, y1: number, x2: number, y2: number): number => {
        return Math.abs(x1 - x2) + Math.abs(y1 - y2);
    };
    const q = new Heap<[number, number, number]>((a, b) => a[0] - b[0]);
    q.push([0, start[0], start[1]]);
    const n = 1000000;
    const vis: Set<number> = new Set();
    let ans = 1 << 30;
    while (q.size()) {
        const [d, x, y] = q.pop();
        const k = x * n + y;
        if (vis.has(k)) {
            continue;
        }
        vis.add(k);
        ans = Math.min(ans, d + dist(x, y, target[0], target[1]));
        for (const [x1, y1, x2, y2, cost] of specialRoads) {
            q.push([d + dist(x, y, x1, y1) + cost, x2, y2]);
        }
    }
    return ans;
}

type Compare<T> = (lhs: T, rhs: T) => number;

class Heap<T = number> {
    data: Array<T | null>;
    lt: (i: number, j: number) => boolean;
    constructor();
    constructor(data: T[]);
    constructor(compare: Compare<T>);
    constructor(data: T[], compare: Compare<T>);
    constructor(data: T[] | Compare<T>, compare?: (lhs: T, rhs: T) => number);
    constructor(
        data: T[] | Compare<T> = [],
        compare: Compare<T> = (lhs: T, rhs: T) => (lhs < rhs ? -1 : lhs > rhs ? 1 : 0),
    ) {
        if (typeof data === 'function') {
            compare = data;
            data = [];
        }
        this.data = [null, ...data];
        this.lt = (i, j) => compare(this.data[i]!, this.data[j]!) < 0;
        for (let i = this.size(); i > 0; i--) this.heapify(i);
    }

    size(): number {
        return this.data.length - 1;
    }

    push(v: T): void {
        this.data.push(v);
        let i = this.size();
        while (i >> 1 !== 0 && this.lt(i, i >> 1)) this.swap(i, (i >>= 1));
    }

    pop(): T {
        this.swap(1, this.size());
        const top = this.data.pop();
        this.heapify(1);
        return top!;
    }

    top(): T {
        return this.data[1]!;
    }
    heapify(i: number): void {
        while (true) {
            let min = i;
            const [l, r, n] = [i * 2, i * 2 + 1, this.data.length];
            if (l < n && this.lt(l, min)) min = l;
            if (r < n && this.lt(r, min)) min = r;
            if (min !== i) {
                this.swap(i, min);
                i = min;
            } else break;
        }
    }

    clear(): void {
        this.data = [null];
    }

    private swap(i: number, j: number): void {
        const d = this.data;
        [d[i], d[j]] = [d[j], d[i]];
    }
}
func minimumCost(start []int, target []int, specialRoads [][]int) int {
	ans := 1 << 30
	const n int = 1e6
	pq := hp{{0, start[0], start[1]}}
	vis := map[int]bool{}
	for len(pq) > 0 {
		p := pq[0]
		heap.Pop(&pq)
		d, x, y := p.d, p.x, p.y
		if vis[x*n+y] {
			continue
		}
		vis[x*n+y] = true
		ans = min(ans, d+dist(x, y, target[0], target[1]))
		for _, r := range specialRoads {
			x1, y1, x2, y2, cost := r[0], r[1], r[2], r[3], r[4]
			heap.Push(&pq, tuple{d + dist(x, y, x1, y1) + cost, x2, y2})
		}
	}
	return ans
}

func dist(x1, y1, x2, y2 int) int {
	return abs(x1-x2) + abs(y1-y2)
}

func abs(x int) int {
	if x < 0 {
		return -x
	}
	return x
}

type tuple struct {
	d, x, y int
}
type hp []tuple

func (h hp) Len() int           { return len(h) }
func (h hp) Less(i, j int) bool { return h[i].d < h[j].d }
func (h hp) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }
func (h *hp) Push(v any)        { *h = append(*h, v.(tuple)) }
func (h *hp) Pop() any          { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v }
Try this approach in the editor

Complexity comparison

ApproachComplexity
Approach 1: Dijkstra's Algorithm

Time Complexity: O((N + M) * log(N + M)), where N is the number of special roads, and M is the number of possible positions considered.
Space Complexity: O(N + M), due to the priority queue and visited set.

Approach 2: Bellman-Ford Algorithm

Time Complexity: O(N * M), relying heavily on re-evaluating each edge relative to every node assessed.
Space Complexity: O(N), arising from the array representation of edges and storage required for managing distances.

Dijkstra–

Complexity analysis

ApproachTimeSpaceWhen to Use
Dijkstra's Algorithm with Priority QueueO(n log n)O(n)Best general solution for non-negative weighted graphs and optimal interview answer
Bellman-Ford AlgorithmO(n^2)O(n)Useful when implementing generic edge relaxation or when negative edges could exist

Frequently asked questions

Is Minimum Cost of a Path With Special Roads easy or hard?

The problem is rated Medium because the main challenge is recognizing the hidden graph structure. Once the coordinates are treated as nodes and edges are defined using Manhattan distance and special roads, applying Dijkstra’s algorithm becomes straightforward.

Minimum Cost of a Path With Special Roads Python/Java solution

Python and Java solutions typically implement Dijkstra’s algorithm using a priority queue (heapq in Python or PriorityQueue in Java). The algorithm stores distances for each special road endpoint and updates them through relaxation steps until the minimum cost to the target is found.

How to solve Minimum Cost of a Path With Special Roads in O(n log n)?

Construct a graph consisting of the start position and all special road endpoints. Compute edge costs using Manhattan distance and the provided special road cost. Run Dijkstra’s algorithm with a min-heap to repeatedly relax the shortest known distance to each node. The heap ensures efficient updates, giving an overall O(n log n) runtime.

What is the best approach for Minimum Cost of a Path With Special Roads?

Dijkstra’s algorithm is the best approach. Model the start point and all special road endpoints as nodes in a graph, then use a priority queue to always process the lowest-cost position first. Each step compares Manhattan distance travel with special road edges. This produces an optimal shortest path in O(n log n) time.

Is Minimum Cost of a Path With Special Roads asked at Google/Amazon/Meta?

Shortest path problems like this frequently appear in interviews at companies such as Google, Amazon, and Meta. Variants often test graph modeling, Dijkstra’s algorithm, and recognizing when a grid problem should be converted into a graph with weighted edges.

What data structure is used in Minimum Cost of a Path With Special Roads?

The key data structure is a priority queue (min-heap) used in Dijkstra’s algorithm. It always selects the node with the smallest current distance for expansion. Additional structures include arrays or hash maps to store the minimum cost for each coordinate node.

What is the time complexity of Minimum Cost of a Path With Special Roads?

Using Dijkstra’s algorithm, the time complexity is O(n log n), where n is the number of special roads. Each node expansion uses a priority queue and relaxes edges to other relevant coordinates. The space complexity is O(n) to store distances and the heap.

Comments

Now write it yourselfClose this page and solve Minimum Cost of a Path With Special Roads in the editor, without looking.
Practise Minimum Cost of a Path With Special Roads