Welcome to Subscribe On Youtube
Formatted question description: https://leetcode.ca/all/656.html
656. Coin Path
Level
Hard
Description
Given an array A
(index starts at 1
) consisting of N integers: A1, A2, …, AN and an integer B
. The integer B
denotes that from any place (suppose the index is i
) in the array A
, you can jump to any one of the place in the array A
indexed i+1
, i+2
, …, i+B
if this place can be jumped to. Also, if you step on the index i
, you have to pay Ai coins. If Ai is -1, it means you cant jump to the place indexed i
in the array.
Now, you start from the place indexed 1
in the array A
, and your aim is to reach the place indexed N
using the minimum coins. You need to return the path of indexes (starting from 1 to N) in the array you should take to get to the place indexed N
using minimum coins.
If there are multiple paths with the same cost, return the lexicographically smallest such path.
If it’s not possible to reach the place indexed N then you need to return an empty array.
Example 1:
Input: [1,2,4,-1,2], 2
Output: [1,3,5]
Example 2:
Input: [1,2,4,-1,2], 1
Output: []
Note:
- Path Pa1, Pa2, …, Pan is lexicographically smaller than Pb1, Pb2, …, Pbm, if and only if at the first
i
where Pai and Pbi differ, Pai < Pbi; when no suchi
exists, thenn
<m
. - A1 >= 0. A2, …, AN (if exist) will in the range of [-1, 100].
- Length of A is in the range of [1, 1000].
- B is in the range of [1, 100].
Solution
Use dynamic programming. Create an array dp
and an array next
of length A.length
, where dp[i]
represents the total cost starting from index i
to the end, and next[i]
represents the next index of index i
in the path with minimum cost.
Initialize dp
such that all elements are Integer.MAX_VALUE
and initialize next
such that all elements are A.length
. If the last element in A
is not -1, then set the last element of dp
to be the last element of A
.
Loop over A
backwards from index A.length - 2
to 0. At each index i
, if A[i]
is -1, then the place cannot be jumped to, so continue. For each index j
from i + 1
to i + B
(or A.length - 1
if i + B
exceeds A.length - 1
), if dp[j]
is Integer.MAX_VALUE
, continue since it is impossible to reach the end from j
. Otherwise, if dp[j] + A[i] < dp[i]
, then update dp[i] = dp[j] + A[i]
and next[i] = j
.
If dp[0]
is Integer.MAX_VALUE
, then no path exists, so return an empty list. Otherwise, starting from index 0 to find a path that reaches the end, and return the path as a list.
-
class Solution { public List<Integer> cheapestJump(int[] A, int B) { List<Integer> path = new ArrayList<Integer>(); int length = A.length; int[] dp = new int[length]; Arrays.fill(dp, Integer.MAX_VALUE); if (A[length - 1] != -1) dp[length - 1] = A[length - 1]; int[] next = new int[length]; Arrays.fill(next, length); for (int i = length - 2; i >= 0; i--) { if (A[i] == -1) continue; int start = i + 1, end = Math.min(i + B, length - 1); for (int j = start; j <= end; j++) { if (dp[j] == Integer.MAX_VALUE) continue; if (dp[j] + A[i] < dp[i]) { dp[i] = dp[j] + A[i]; next[i] = j; } } } if (dp[0] == Integer.MAX_VALUE) return path; int index = 0; while (index < length) { path.add(index + 1); index = next[index]; } return path; } }
-
class Solution { public: vector<int> cheapestJump(vector<int>& coins, int maxJump) { int n = coins.size(); vector<int> ans; if (coins[n - 1] == -1) { return ans; } int f[n]; const int inf = 1 << 30; f[n - 1] = coins[n - 1]; for (int i = n - 2; ~i; --i) { f[i] = inf; if (coins[i] != -1) { for (int j = i + 1; j < min(n, i + maxJump + 1); ++j) { f[i] = min(f[i], f[j] + coins[i]); } } } if (f[0] == inf) { return ans; } for (int i = 0, s = f[0]; i < n; ++i) { if (f[i] == s) { s -= coins[i]; ans.push_back(i + 1); } } return ans; } };
-
class Solution: def cheapestJump(self, coins: List[int], maxJump: int) -> List[int]: if coins[-1] == -1: return [] n = len(coins) f = [inf] * n f[-1] = coins[-1] for i in range(n - 2, -1, -1): if coins[i] != -1: for j in range(i + 1, min(n, i + maxJump + 1)): if f[i] > f[j] + coins[i]: f[i] = f[j] + coins[i] if f[0] == inf: return [] ans = [] s = f[0] for i in range(n): if f[i] == s: s -= coins[i] ans.append(i + 1) return ans
-
func cheapestJump(coins []int, maxJump int) (ans []int) { n := len(coins) if coins[n-1] == -1 { return } f := make([]int, n) f[n-1] = coins[n-1] const inf = 1 << 30 for i := n - 2; i >= 0; i-- { f[i] = inf if coins[i] != -1 { for j := i + 1; j < n && j < i+maxJump+1; j++ { if f[i] > f[j]+coins[i] { f[i] = f[j] + coins[i] } } } } if f[0] == inf { return } for i, s := 0, f[0]; i < n; i++ { if f[i] == s { s -= coins[i] ans = append(ans, i+1) } } return }
-
function cheapestJump(coins: number[], maxJump: number): number[] { const n = coins.length; const ans: number[] = []; if (coins[n - 1] == -1) { return ans; } const inf = 1 << 30; const f: number[] = new Array(n).fill(inf); f[n - 1] = coins[n - 1]; for (let i = n - 2; i >= 0; --i) { if (coins[i] !== -1) { for (let j = i + 1; j < Math.min(n, i + maxJump + 1); ++j) { f[i] = Math.min(f[i], f[j] + coins[i]); } } } if (f[0] === inf) { return ans; } for (let i = 0, s = f[0]; i < n; ++i) { if (f[i] == s) { s -= coins[i]; ans.push(i + 1); } } return ans; }