[LeetCode] 656. Coin Path 硬币路径
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 can’t 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].
给一个数组A,数组元素的值代表cost,一个整数B表示能走的最大步数。从第1个位置开始走,每次能走的步数是B步以内,走到某个位置就要付出该位置的cost,目标是到达最末尾位置,使得付出总cost值最小,输出所有路径。如果某个位置是-1,不可以走这个位置。如果有多个路径,输出按字母顺序排列。
解法:DP, 从后往前跳。首先判断最后一个位置是否为-1,如果是说明无法到达最后位置,返回空。用一个一维数组dp记录跳到i位置所用的最小cost, 从i位置跳时有B种跳法,再去判断每一个跳法的dp值。
dp[i] = A[i] + dp[j] (dp[j]为从B种跳法中的一种的dp值)
Python:
# Time: O(n * B) # Space: O(n) class Solution(object): def cheapestJump(self, A, B): """ :type A: List[int] :type B: int :rtype: List[int] """ result = [] if not A or A[-1] == -1: return result n = len(A) dp, next_pos = [float("inf")] * n, [-1] * n dp[n-1] = A[n-1] for i in reversed(xrange(n-1)): if A[i] == -1: continue for j in xrange(i+1, min(i+B+1,n)): if A[i] + dp[j] < dp[i]: dp[i] = A[i] + dp[j] next_pos[i] = j if dp[0] == float("inf"): return result k = 0 while k != -1: result.append(k+1) k = next_pos[k] return result
C++:
class Solution { public: vector<int> cheapestJump(vector<int>& A, int B) { if (A.back() == -1) return {}; int n = A.size(); vector<int> res, dp(n, INT_MAX), pos(n, -1); dp[n - 1] = A[n - 1]; for (int i = n - 2; i >= 0; --i) { if (A[i] == -1) continue; for (int j = i + 1; j <= min(i + B, n - 1); ++j) { if (dp[j] == INT_MAX) continue; if (A[i] + dp[j] < dp[i]) { dp[i] = A[i] + dp[j]; pos[i] = j; } } } if (dp[0] == INT_MAX) return res; for (int cur = 0; cur != -1; cur = pos[cur]) { res.push_back(cur + 1); } return res; } };
C++:
class Solution { public: vector<int> cheapestJump(vector<int>& A, int B) { if (A.back() == -1) return {}; int n = A.size(); vector<int> res, dp(n, INT_MAX), pos(n, -1), len(n, 0); dp[0] = 0; for (int i = 0; i < n; ++i) { if (A[i] == -1) continue; for (int j = max(0, i - B); j < i; ++j) { if (dp[j] == INT_MAX) continue; int t = A[i] + dp[j]; if (t < dp[i] || (t == dp[i] && len[i] < len[j] + 1)) { dp[i] = t; pos[i] = j; len[i] = len[j] + 1; } } } if (dp[n - 1] == INT_MAX) return res; for (int cur = n - 1; cur != -1; cur = pos[cur]) { res.insert(res.begin(), cur + 1); } return res; } };
C++:
class Solution { public: vector<int> cheapestJump(vector<int>& A, int B) { vector<int> result; if (A.empty() || A.back() == -1) { return result; } const int n = A.size(); vector<int> dp(n, numeric_limits<int>::max()), next(n, -1); dp[n - 1] = A[n - 1]; for (int i = n - 2; i >= 0; --i) { if (A[i] == -1) { continue; } for (int j = i + 1; j <= min(i + B, n - 1); ++j) { if (dp[j] == numeric_limits<int>::max()) { continue; } if (A[i] + dp[j] < dp[i]) { dp[i] = A[i] + dp[j]; next[i] = j; } } } if (dp[0] == numeric_limits<int>::max()) { return result; } int k = 0; while (k != -1) { result.emplace_back(k + 1); k = next[k]; } return result; } };
类似题目:
[LeetCode] 198. House Robber 打家劫舍
[LeetCode] 213. House Robber II 打家劫舍 II
[LeetCode] 45. Jump Game II 跳跃游戏 II
All LeetCode Questions List 题目汇总