Given an array A (index starts at 1) consisting of N integers: A1, A2, ..., AN and an integer B. The integer Bdenotes 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+1i+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:

  1. 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 such i exists, then n < m.
  2. A1 >= 0. A2, ..., AN (if exist) will in the range of [-1, 100].
  3. Length of A is in the range of [1, 1000].
  4. B is in the range of [1, 100].

这道题给了我们一个数组A,又给了我们一个整数B,表示能走的最大步数,数组上的每个数字都是cost值,如果到达某个位置,就要加上该位置上的数字,其实位置是在第一个数字上,目标是到达末尾位置,我们需要让总cost值最小,并输入路径,如果cos相同的话,输出字母顺序小的那个路径。还有就是如果数组上的某个位置为-1的话,表示到达该位置后不能再去下一个位置,而且数组末位置不能为-1。博主最开始写了一个递归的解法,结果MLE了,看来这道题对内存使用的管控极为苛刻。所以我们不能将所有的候选路径都存在内存中,而是应该建立祖先数组,即数组上每个位置放其父结点的位置,有点像联合查找Union Find中的root数组,再最后根据这个祖先数组来找出正确的路径。由于需要找出cost最小的路径,所以我们可以考虑用dp数组,其中dp[i]表示从开头到位置i的最小cost值,但是如果我们从后往前跳,那么dp[i]就是从末尾到位置i的最小cost值。

我们首先判断数组A的末尾数字是否为-1,是的话直接返回空集。否则就新建结果res数组,dp数组,和pos数组,其中dp数组都初始化为整型最大值,pos数组都初始化为-1。然后将dp数组的最后一个数字赋值为数组A的尾元素。因为我们要从后往前跳,那我们从后往前遍历,如果遇到数字-1,说明不能往前跳了,直接continue继续循环,然后对于每个遍历到的数字,我们都要遍历其上一步可能的位置的dp[j]值来更新当前dp[i]值,由于限制了步数B,所以最多能到i+B,为了防止越界,要取i+B和n-1中的较小值为界限,如果上一步dp[j]值为INT_MAX,说明上一个位置无法跳过来,直接continue,否则看上一个位置dp[j]值加上当前cost值A[i],如果小于dp[i],说明dp[i]需要更新,并且建立祖先数组的映射pos[i] = j。最后在循环结束后,我们判断dp[0]的值,如果是INT_MAX,说明没有跳到首位置,直接返回空集,否则我们就通过pos数组来取路径。我们从前往后遍历pos数组来取位置,直到遇到-1停止。另外要说明的就是,这种从后往前遍历的模式得到的路径一定是字母顺序最小的,zestypanda大神的帖子中有证明,不过博主没太看懂-.-|||,可以带这个例子尝试:

A = [0, 0, 0], B = 2

上面这个例子得到的结果是[1, 2, 3],是字母顺序最小的路径,而相同的cost路径[1, 3],就不是字母顺序最小的路径,参见代码如下:

解法一:

class Solution {
public:
vector<int> cheapestJump(vector<int>& A, int B) {
if (A.back() == -) return {};
int n = A.size();
vector<int> res, dp(n, INT_MAX), pos(n, -);
dp[n - ] = A[n - ];
for (int i = n - ; i >= ; --i) {
if (A[i] == -) continue;
for (int j = i + ; j <= min(i + B, n - ); ++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[] == INT_MAX) return res;
for (int cur = ; cur != -; cur = pos[cur]) {
res.push_back(cur + );
}
return res;
}
};

下面这种方法是正向遍历的解法,正向跳的话就需要另一个数组len,len[i]表示从开头到达位置i的路径的长度,如果两个路径的cost相同,那么一定是路径长度大的字母顺序小,可以参见例子 A = [0, 0, 0], B = 2。

具体的写法就不讲了,跟上面十分类似,参考上面的讲解,需要注意的就是更新的判定条件中多了一个t == dp[i] && len[i] < len[j] + 1,就是判断当cost相同时,我们取长度大路径当作结果保存。还有就是最后查找路径时要从末尾往前遍历,只要遇到-1时停止,参见代码如下:

解法二:

class Solution {
public:
vector<int> cheapestJump(vector<int>& A, int B) {
if (A.back() == -) return {};
int n = A.size();
vector<int> res, dp(n, INT_MAX), pos(n, -), len(n, );
dp[] = ;
for (int i = ; i < n; ++i) {
if (A[i] == -) continue;
for (int j = max(, 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] + )) {
dp[i] = t;
pos[i] = j;
len[i] = len[j] + ;
}
}
}
if (dp[n - ] == INT_MAX) return res;
for (int cur = n - ; cur != -; cur = pos[cur]) {
res.insert(res.begin(), cur + );
}
return res;
}
};

类似题目:

House Robber II

House Robber

Frog Jump

Jump Game

Jump Game II

参考资料:

https://discuss.leetcode.com/topic/98399/c-dp-o-nb-time-o-n-space

https://discuss.leetcode.com/topic/98491/java-22-lines-solution-with-proof

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Coin Path 硬币路径的更多相关文章

  1. [LeetCode] 656. Coin Path 硬币路径

    Given an array A (index starts at 1) consisting of N integers: A1, A2, ..., AN and an integer B. The ...

  2. [LeetCode] 112. Path Sum 路径和

    Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all ...

  3. [LeetCode] Coin Change 硬币找零

    You are given coins of different denominations and a total amount of money amount. Write a function ...

  4. [LeetCode] Simplify Path 简化路径

    Given an absolute path for a file (Unix-style), simplify it. For example,path = "/home/", ...

  5. [leetcode]112. Path Sum路径和(是否有路径)

    Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all ...

  6. 【LeetCode】Path Sum(路径总和)

    这道题是LeetCode里的第112道题.是我在学数据结构——二叉树的时候碰见的题.题目要求: 给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和 ...

  7. LeetCode 112. Path Sum路径总和 (C++)

    题目: Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up ...

  8. [LeetCode] 113. Path Sum II 路径和 II

    Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given su ...

  9. [LeetCode] 437. Path Sum III 路径和 III

    You are given a binary tree in which each node contains an integer value. Find the number of paths t ...

随机推荐

  1. Android开发心得-使用File ExPlorer无法访问系统内部文件

    问题:本机在获得ROOT权限后,使用Eclipse自带的File Explorer访问/data/data下各APP的存储文件,均无法打开.更换另外一个设备后,情况正常.Sumsung的有些机型在获得 ...

  2. 转载---SuperMap GIS 9D SP1学习视频播单

    转自:http://blog.csdn.net/supermapsupport/article/details/79219102 SuperMap GIS 9D SP1学习视频播单 我们一直在思考什么 ...

  3. C# MVC NPOI导出

    前台: <form id="fmexp" method="post" target="_blank"> </form> ...

  4. SpringMVC DispatcherServlet 启动和加载过程(源码调试)

    在阅读本文前,最好先阅读以下内容(当然,如果对 Servlet 已经有所了解,则可跳过): http://www.cnblogs.com/cyhbyw/p/8682078.html http://ww ...

  5. gitignore忽略规则

    我们用git提交本地代码时,有些文件或日志是不需要提交的,这个时候可以用.gitignore来解决这个问题: 首先,我们需要创建一个.gitignore文件,用命令输入 touch .gitignor ...

  6. 团队作业6——展示博客(Alpha版本)

    Deadline: 2017-12-3  23:00PM,以博客发表日期为准   评分基准 按时交 - 有分,检查的项目包括后文的两个方面 团队成员介绍 Alpha阶段进展 团队合作,各成员分工 Be ...

  7. 团队作业4——第一次项目冲刺(Alpha版本) Day 1

    小队@JMUZJB-集美震惊部 一.Daily Scrum Meeting照片 二.Burndown Chart 燃尽图 三.项目进展 1.界面 屏幕开发中,原型设计完毕. 2.服务器 服务器由学校提 ...

  8. 201621123057 《Java程序设计》第8周学习总结

    1. 本周学习总结 思维导图归纳总结集合相关内容. 2. 书面作业 1. ArrayList代码分析 1.1 解释ArrayList的contains源代码 ArrayList是允许重复的,但当用它来 ...

  9. 201621123043 《Java程序设计》第11周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 2. 书面作业 本次PTA作业题集多线程 1. 源代码阅读:多线程程序BounceThread 1.1 BallR ...

  10. JAVAGUI设计步骤

    ①创建容器 首先要创建一个GUI应用程序,需要创建一个用于容纳所有其它GUI组件元素的载体,Java中称为容器.典型的包括窗口(Window).框架(Frame/JFrame).对话框(Dialog/ ...