-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
92 changed files
with
2,920 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# Cheapest Flights Within K Stops | ||
|
||
LeetCode #: [787](https://leetcode.com/problems/cheapest-flights-within-k-stops/) | ||
|
||
Difficulty: Medium | ||
|
||
Topics: Dynamic Programming, Heap, Breadth-first Search. | ||
|
||
## Problem | ||
|
||
There are `n` cities connected by `m` flights. Each flight starts from city `u` and arrives at `v` with a price `w`. | ||
|
||
Now given all the cities and flights, together with starting city `src` and the destination `dst`, your task is to find the cheapest price from `src` to `dst` with up to `k` stops. If there is no such route, output `-1`. | ||
|
||
Example 1: | ||
|
||
![image](https://s3-lc-upload.s3.amazonaws.com/uploads/2018/02/16/995.png) | ||
|
||
```text | ||
Input: | ||
n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]] | ||
src = 0, dst = 2, k = 1 | ||
Output: 200 | ||
Explanation: | ||
The cheapest price from city 0 to city 2 with at most 1 stop costs 200, as marked red in the picture. | ||
``` | ||
|
||
Example 2: | ||
|
||
![image](https://s3-lc-upload.s3.amazonaws.com/uploads/2018/02/16/995.png) | ||
|
||
```text | ||
Input: | ||
n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]] | ||
src = 0, dst = 2, k = 0 | ||
Output: 500 | ||
Explanation: | ||
The cheapest price from city 0 to city 2 with at most 0 stop costs 500, as marked blue in the picture. | ||
``` | ||
|
||
Constraints: | ||
|
||
- The number of nodes `n` will be in range `[1, 100]`, with nodes labeled from `0` to `n - 1`. | ||
- The size of flights will be in range `[0, n * (n - 1) / 2]`. | ||
- The format of each flight will be `(src, dst, price)`. | ||
- The price of each flight will be in the range `[1, 10000]`. | ||
- `k` is in the range of `[0, n - 1]`. | ||
- There will not be any duplicated flights or self cycles. | ||
|
||
## Solution Explanation | ||
|
||
The idea is based on [Dijkstra's algorithm](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm). | ||
|
||
Reference: [[Java/Python] Priority Queue Solution](https://leetcode.com/problems/cheapest-flights-within-k-stops/discuss/115541/JavaPython-Priority-Queue-Solution) by [lee215](https://leetcode.com/lee215) |
53 changes: 53 additions & 0 deletions
53
problems/cheapest-flights-within-k-stops/findCheapestPrice.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
const sortedIndexBy = require('lodash/sortedIndexBy') | ||
|
||
// get a src->dst->price map object based on flights. | ||
const getSrcDstPriceMap = (flights) => { | ||
const srcDstPriceMap = new Map() | ||
|
||
for (let i = 0; i < flights.length; i++) { | ||
const [src, dst, price] = flights[i] | ||
srcDstPriceMap.set(src, (srcDstPriceMap.get(src) || new Map()).set(dst, price)) | ||
} | ||
|
||
return srcDstPriceMap | ||
} | ||
|
||
/** | ||
* @param {number} n | ||
* @param {number[][]} flights | ||
* @param {number} src | ||
* @param {number} dst | ||
* @param {number} K | ||
* @return {number} | ||
*/ | ||
const findCheapestPrice = function (n, flights, src, dst, k) { | ||
const srcDstPriceMap = getSrcDstPriceMap(flights) | ||
|
||
// a priority queue that sorts based on accumulated price. | ||
// each item is in the format [accumulated price, current city, remaining flights]. | ||
// note that remaining flights is equal to k+1. | ||
const queue = [] | ||
queue.push([0, src, k + 1]) | ||
|
||
while (queue.length > 0) { | ||
const [accPrice, city, remainingFlights] = queue.shift() | ||
|
||
if (city === dst) { | ||
return accPrice | ||
} | ||
|
||
if (remainingFlights > 0) { | ||
const adjDstPriceMap = srcDstPriceMap.get(city) || new Map() | ||
|
||
for (const [dst, price] of adjDstPriceMap.entries()) { | ||
const next = [accPrice + price, dst, remainingFlights - 1] | ||
const idx = sortedIndexBy(queue, next, (o) => o[0]) | ||
queue.splice(idx, 0, next) | ||
} | ||
} | ||
} | ||
|
||
return -1 | ||
} | ||
|
||
module.exports = findCheapestPrice |
49 changes: 49 additions & 0 deletions
49
problems/cheapest-flights-within-k-stops/findCheapestPrice.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
const findCheapestPrice = require('./findCheapestPrice') | ||
|
||
test('Example 1', () => { | ||
const n = 3 | ||
const flights = [[0, 1, 100], [1, 2, 100], [0, 2, 500]] | ||
const src = 0 | ||
const dst = 2 | ||
const k = 1 | ||
|
||
const result = findCheapestPrice(n, flights, src, dst, k) | ||
|
||
expect(result).toBe(200) | ||
}) | ||
|
||
test('Example 2', () => { | ||
const n = 3 | ||
const flights = [[0, 1, 100], [1, 2, 100], [0, 2, 500]] | ||
const src = 0 | ||
const dst = 2 | ||
const k = 0 | ||
|
||
const result = findCheapestPrice(n, flights, src, dst, k) | ||
|
||
expect(result).toBe(500) | ||
}) | ||
|
||
test('no such route should return -1', () => { | ||
const n = 4 | ||
const flights = [[0, 1, 100], [1, 2, 100], [0, 2, 500], [2, 3, 200]] | ||
const src = 0 | ||
const dst = 3 | ||
const k = 0 | ||
|
||
const result = findCheapestPrice(n, flights, src, dst, k) | ||
|
||
expect(result).toBe(-1) | ||
}) | ||
|
||
test('intermediate city 4 has no flight out', () => { | ||
const n = 4 | ||
const flights = [[0, 1, 100], [1, 4, 120], [0, 2, 500], [2, 3, 200]] | ||
const src = 0 | ||
const dst = 3 | ||
const k = 5 | ||
|
||
const result = findCheapestPrice(n, flights, src, dst, k) | ||
|
||
expect(result).toBe(700) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# Coin Change 2 | ||
|
||
LeetCode #: [518](https://leetcode.com/problems/coin-change-2/) | ||
|
||
Difficulty: Medium | ||
|
||
Topics: - | ||
|
||
## Problem | ||
|
||
You are given coins of different denominations and a total amount of money. Write a function to compute the number of combinations that make up that amount. You may assume that you have infinite number of each kind of coin. | ||
|
||
Example 1: | ||
|
||
```text | ||
Input: amount = 5, coins = [1, 2, 5] | ||
Output: 4 | ||
Explanation: there are four ways to make up the amount: | ||
5=5 | ||
5=2+2+1 | ||
5=2+1+1+1 | ||
5=1+1+1+1+1 | ||
``` | ||
|
||
Example 2: | ||
|
||
```text | ||
Input: amount = 3, coins = [2] | ||
Output: 0 | ||
Explanation: the amount of 3 cannot be made up just with coins of 2. | ||
``` | ||
|
||
Example 3: | ||
|
||
```text | ||
Input: amount = 10, coins = [10] | ||
Output: 1 | ||
``` | ||
|
||
Note: | ||
|
||
You can assume that | ||
|
||
- `0 <= amount <= 5000` | ||
- `1 <= coin <= 5000` | ||
- the number of coins is less than 500 | ||
- the answer is guaranteed to fit into signed 32-bit integer | ||
|
||
## Solution Explanation | ||
|
||
This is a [knapsack problem](https://en.wikipedia.org/wiki/Knapsack_problem) which can be solved by using dynamic programming. | ||
|
||
Reference: [Knapsack problem - Java solution with thinking process O(nm) Time and O(m) Space](https://leetcode.com/problems/coin-change-2/discuss/99212/Knapsack-problem-Java-solution-with-thinking-process-O(nm)-Time-and-O(m)-Space) by [tankztc](https://leetcode.com/tankztc) | ||
|
||
## Complexity Analysis | ||
|
||
Assume m is the amount and n is the number of coins. | ||
|
||
Time complexity: O(mn) | ||
|
||
Space complexity: O(m) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/** | ||
* @param {number} amount | ||
* @param {number[]} coins | ||
* @return {number} | ||
*/ | ||
const change = function (amount, coins) { | ||
const dp = new Array(amount + 1).fill(0) | ||
dp[0] = 1 | ||
for (const coin of coins) { | ||
for (let i = coin; i <= amount; i++) { | ||
dp[i] += dp[i - coin] | ||
} | ||
} | ||
|
||
return dp[amount] | ||
} | ||
|
||
module.exports = change |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
const change = require('./change') | ||
|
||
test('Example 1', () => { | ||
const amount = 5 | ||
const coins = [1, 2, 5] | ||
|
||
const result = change(amount, coins) | ||
|
||
expect(result).toBe(4) | ||
}) | ||
|
||
test('Example 2', () => { | ||
const amount = 3 | ||
const coins = [2] | ||
|
||
const result = change(amount, coins) | ||
|
||
expect(result).toBe(0) | ||
}) | ||
|
||
test('Example 3', () => { | ||
const amount = 10 | ||
const coins = [10] | ||
|
||
const result = change(amount, coins) | ||
|
||
expect(result).toBe(1) | ||
}) | ||
|
||
test('amount 0 should return 1 (empty combination)', () => { | ||
const amount = 0 | ||
const coins = [1, 2, 5] | ||
|
||
const result = change(amount, coins) | ||
|
||
expect(result).toBe(1) | ||
}) |
Oops, something went wrong.