[LeetCode] Coin Path 硬币路径
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+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
iwhere Pai and Pbi differ, Pai < Pbi; when no suchiexists, 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,又给了我们一个整数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;
}
};
类似题目:
参考资料:
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 硬币路径的更多相关文章
- [LeetCode] 656. Coin Path 硬币路径
Given an array A (index starts at 1) consisting of N integers: A1, A2, ..., AN and an integer B. The ...
- [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 ...
- [LeetCode] Coin Change 硬币找零
You are given coins of different denominations and a total amount of money amount. Write a function ...
- [LeetCode] Simplify Path 简化路径
Given an absolute path for a file (Unix-style), simplify it. For example,path = "/home/", ...
- [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 ...
- 【LeetCode】Path Sum(路径总和)
这道题是LeetCode里的第112道题.是我在学数据结构——二叉树的时候碰见的题.题目要求: 给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和 ...
- 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 ...
- [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 ...
- [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 ...
随机推荐
- jQuery学习笔记 .addClass()/.removeClass()简单学习
使用jQuery或javaScript来动态改变页面中某个或部分元素的样式,为了实现这样的功能,我们往往都是使用jQuery或javaScript来控制HTML中DOM的类名(class)从而实现增加 ...
- 关于Redis数据库 ---- 基础篇
Redis数据库也被称为数据结构数据库,因为存储基于key-value模式. 其中,value值可以为字符串(string),哈希(map),列表(list),集合(set)和有序集合(zset). ...
- 删除日志释放空间最好不要用rm
目前在维护一些服务器有一个根目录空间经常告警no space left ,切到/var/log 目录下du -sh * 的时候,发现有一个authlog占了12G,然后立马执行了rm authlog: ...
- 赛博杯-HMI流水灯-stack
stack(ret2libc) 分析 首先checksec一下,发现没开栈保护,可能是栈溢出. [*] '/root/Desktop/bin/pwn/stack_/stack' Arch: i386- ...
- 2017-2018-1 20155306 《信息安全系统设计基础》Mybash的实现
2017-2018-1 20155306 <信息安全系统设计基础>Mybash的实现 要求: 使用fork,exec,wait实现mybash 写出伪代码,产品代码和测试代码 发表知识理解 ...
- 2018上C语言程序设计(高级)作业- 第2次作业
作业要求一 提交截图: 6-7: 6-8: 6-9: 7-1: 作业要求二 题目6-7删除字符中数字字符 1.设计思路: (1)第一步:本题要求是删除字符中的数字字符,我的主要思路是通过数组遍历若遇到 ...
- Lucene 的索引文件锁原理
Lucene 的索引文件锁原理 2016/11/24 · IT技术 · lucene 环境 Lucene 6.0.0Java “1.8.0_111”OS Windows 7 Ultimate 线程 ...
- SELinux与进程管理
- mysql5.7在windows下面的主从复制配置
目标:自动同步Master 服务器上面的Demo数据库到Slave 服务器的Demo数据库中. 对于一些操作系统比较强而使用频率又不高的东西,往往好久不去弄就忘记了,所以要经常记录起来,方便日后查阅. ...
- thinkphp中的常见静态常亮
thinkphp __PUBLIC__的定义 __ROOT__等常量的定义 1 2 3 4 5 6 7 8 9 '__TMPL__' => APP_TMPL_PATH, // 项目 ...