skip to Main Content

I am trying to solve LeetCode problem #787, "Cheapest Flights Within K Stops."

"There are n cities connected by some number of flights. You are given an array flights where flights[i] = [fromi, toi, pricei] indicates that there is a flight from city fromi to city toi with cost pricei. You are also given three integers src, dst, and k, return the cheapest price from src to dst with at most k stops. If there is no such route, return -1."

However, I am encountering an issue with a specific testcase:

flights = [[0,1,5],[1,2,5],[0,3,2],[3,1,2],[1,4,1],[4,2,1]], 
n = 5, 
src = 0, 
dst = 2, 
k = 2

The expected answer is 7, but my code is returning 9. I have spent the last 2 hours debugging the code, but I cant seem to find the issue. I would appreciate if someone can point out whats wrong with the code.

code:

class minHeap {
    constructor() {
        this.nodes = []
    }

    enqueue(node, priority, stopsCount) {
        if(this.isEmpty()) {
            this.nodes.push([node, priority, stopsCount])
        } else {
            let added = false;

            for(let i = 0; i < this.nodes.length; i++) {
                if(this.nodes[i][1] > priority) {
                    this.nodes.splice(i, 0, [node, priority, stopsCount])
                    added = true
                    break;
                }
            }

            if(!added) {
                this.nodes.push([node, priority, stopsCount])
            }
        }
    }

    dequeue() {
        return this.nodes.shift()
    }

    isEmpty() {
        return this.nodes.length === 0
    }
}

var findCheapestPrice = function(n, flights, src, dst, k) {
    const graph = {}
    const prices = {}
    for(let i = 0; i < n; i++) {
        graph[i] = []
        if (i == src) {
            prices[i] = 0
        } else {
            prices[i] = Infinity
        }
    }

    for(let [ from, to, price ] of flights) {
        graph[from].push([ to, price ])
    }


    const heap = new minHeap()
    heap.enqueue(src, 0, 0)
    
    while (!heap.isEmpty()) {
        const [ airport, price, stopsCount ] = heap.dequeue()
        
        for (let neighbor of graph[airport]) {
            const [ neighborAirport, neighborPrice ] = neighbor
            const priceToNeighbor = neighborPrice + price
            
            if (prices[neighborAirport] > priceToNeighbor && stopsCount <= k) {
                prices[neighborAirport] = priceToNeighbor
                heap.enqueue(neighborAirport, priceToNeighbor, stopsCount+1)
            }

        }
    }

    
    return prices[dst] == Infinity ? -1 : prices[dst]
};

2

Answers


  1. I don’t have enough time to debug exactly what’s wrong but I feel something is wrong with your enqueuing priority. Removing that optimization causes the program to work correctly:

    class minHeap {
        constructor() {
            this.nodes = []
        }
    
        enqueue(node, priority, stopsCount) {
            // This now work without the priority.
            this.nodes.push([node, priority, stopsCount]);
        }
    
        dequeue() {
            return this.nodes.shift()
        }
    
        isEmpty() {
            return this.nodes.length === 0
        }
    }
    
    var findCheapestPrice = function(n, flights, src, dst, k) {
        const graph = {}
        const prices = {}
        for(let i = 0; i < n; i++) {
            graph[i] = []
            if (i == src) {
                prices[i] = 0
            } else {
                prices[i] = Infinity
            }
        }
    
        for(let [ from, to, price ] of flights) {
            graph[from].push([ to, price ])
        }
    
    
        const heap = new minHeap()
        heap.enqueue(src, 0, 0)
    
        while (!heap.isEmpty()) {
            const [ airport, price, stopsCount ] = heap.dequeue()
            
            for (let neighbor of graph[airport]) {
                const [ neighborAirport, neighborPrice ] = neighbor
                const priceToNeighbor = neighborPrice + price
                
                if (prices[neighborAirport] > priceToNeighbor && stopsCount <= k) {
                    prices[neighborAirport] = priceToNeighbor
                    heap.enqueue(neighborAirport, priceToNeighbor, stopsCount+1)
                }
    
            }
        }
    
        
        return prices[dst] == Infinity ? -1 : prices[dst]
    };
    
    const
      flights = [[0,1,5],[1,2,5],[0,3,2],[3,1,2],[1,4,1],[4,2,1]], 
      n = 6, 
      src = 0, 
      dst = 2, 
      k = 2;
    console.log(findCheapestPrice(n, flights, src, dst, k));

    I tried submitting the above code to LeetCode (sorry about that, I didn’t mean to plagarize, just want to test), it passes all test cases.

    Update: this fix may work by luck though I cannot find a counter example yet. In fact, I think without the priority, it should work for all cases (see comments below and the other answer). Even with this complicated graph this code works:

    enter image description here

    Login or Signup to reply.
  2. The scheme to update and only enqueue stops prioritised by cost doesn’t work in this particular example because the cost to get to airport 4 is set as 5 after 3 stops (including the last): [0,3,2] -> [3,1,2] -> [1,4,1]. But in order to reach airport 2 optimally, we need the interim state where we reach airport 4 with cost 6 but the priority scheme prevents this:

    [0,1,5] -> [1,4,1]
    

    I don’t believe Dijkstra can be used generally to optimise edge cost to a destination where the number of edges is restricted. Other dynamic programming or graph algorithms can assist with that.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search