[LeetCode] Frog Jump 青蛙过河
A frog is crossing a river. The river is divided into x units and at each unit there may or may not exist a stone. The frog can jump on a stone, but it must not jump into the water.
Given a list of stones' positions (in units) in sorted ascending order, determine if the frog is able to cross the river by landing on the last stone. Initially, the frog is on the first stone and assume the first jump must be 1 unit.
If the frog's last jump was k units, then its next jump must be either k - 1, k, or k + 1 units. Note that the frog can only jump in the forward direction.
Note:
- The number of stones is ≥ 2 and is < 1,100.
- Each stone's position will be a non-negative integer < 231.
- The first stone's position is always 0.
Example 1:
[0,1,3,5,6,8,12,17] There are a total of 8 stones.
The first stone at the 0th unit, second stone at the 1st unit,
third stone at the 3rd unit, and so on...
The last stone at the 17th unit. Return true. The frog can jump to the last stone by jumping
1 unit to the 2nd stone, then 2 units to the 3rd stone, then
2 units to the 4th stone, then 3 units to the 6th stone,
4 units to the 7th stone, and 5 units to the 8th stone.
Example 2:
[0,1,2,3,4,8,9,11] Return false. There is no way to jump to the last stone as
the gap between the 5th and 6th stone is too large.
终于等到青蛙过河问题了,一颗赛艇。题目中说青蛙如果上一次跳了k距离,那么下一次只能跳k-1, k, 或k+1的距离,那么青蛙跳到某个石头上可能有多种跳法,由于这道题只是让我们判断青蛙是否能跳到最后一个石头上,并没有让我们返回所有的路径,这样就降低了一些难度。我们可以用递归来做,我们维护一个哈希表,建立青蛙在pos位置和拥有jump跳跃能力时是否能跳到对岸。为了能用一个变量同时表示pos和jump,我们可以将jump左移很多位并或上pos,由于题目中对于位置大小有限制,所以不会产生冲突。我们还是首先判断pos是否已经到最后一个石头了,是的话直接返回true;然后看当前这种情况是否已经出现在哈希表中,是的话直接从哈希表中取结果。如果没有,我们就遍历余下的所有石头,对于遍历到的石头,我们计算到当前石头的距离dist,如果距离小于jump-1,我们接着遍历下一块石头;如果dist大于jump+1,说明无法跳到下一块石头,m[key]赋值为false,并返回false;如果在青蛙能跳到的范围中,我们调用递归函数,以新位置i为pos,距离dist为jump,如果返回true了,我们给m[key]赋值为true,并返回true。如果结束遍历我们给m[key]赋值为false,并返回false,参加代码如下:
解法一:
class Solution {
public:
bool canCross(vector<int>& stones) {
unordered_map<int, bool> m;
return helper(stones, , , m);
}
bool helper(vector<int>& stones, int pos, int jump, unordered_map<int, bool>& m) {
int n = stones.size(), key = pos | jump << ;
if (pos >= n - ) return true;
if (m.count(key)) return m[key];
for (int i = pos + ; i < n; ++i) {
int dist = stones[i] - stones[pos];
if (dist < jump - ) continue;
if (dist > jump + ) return m[key] = false;
if (helper(stones, i, dist, m)) return m[key] = true;
}
return m[key] = false;
}
};
我们也可以用迭代的方法来解,用一个哈希表来建立每个石头和在该位置上能跳的距离之间的映射,建立一个一维dp数组,其中dp[i]表示在位置为i的石头青蛙的弹跳力(只有青蛙能跳到该石头上,dp[i]才大于0),由于题目中规定了第一个石头上青蛙跳的距离必须是1,为了跟后面的统一,我们对青蛙在第一块石头上的弹跳力初始化为0(虽然为0,但是由于题目上说青蛙最远能到其弹跳力+1的距离,所以仍然可以到达第二块石头)。我们用变量k表示当前石头,然后开始遍历剩余的石头,对于遍历到的石头i,我们来找到刚好能跳到i上的石头k,如果i和k的距离大于青蛙在k上的弹跳力+1,则说明青蛙在k上到不了i,则k自增1。我们从k遍历到i,如果青蛙能从中间某个石头上跳到i上,我们更新石头i上的弹跳力和最大弹跳力。这样当循环完成后,我们只要检查最后一个石头上青蛙的最大弹跳力是否大于0即可,参见代码如下:
解法二:
class Solution {
public:
bool canCross(vector<int>& stones) {
unordered_map<int, unordered_set<int>> m;
vector<int> dp(stones.size(), );
m[].insert();
int k = ;
for (int i = ; i < stones.size(); ++i) {
while (dp[k] + < stones[i] - stones[k]) ++k;
for (int j = k; j < i; ++j) {
int t = stones[i] - stones[j];
if (m[j].count(t - ) || m[j].count(t) || m[j].count(t + )) {
m[i].insert(t);
dp[i] = max(dp[i], t);
}
}
}
return dp.back() > ;
}
};
参考资料:
https://discuss.leetcode.com/topic/59337/easy-version-java
https://discuss.leetcode.com/topic/59427/share-my-non-recursive-c-solution-with-simple-comments
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] Frog Jump 青蛙过河的更多相关文章
- [leetcode]403. Frog Jump青蛙过河
A frog is crossing a river. The river is divided into x units and at each unit there may or may not ...
- 403 Frog Jump 青蛙过河
一只青蛙想要过河. 假定河流被等分为 x 个单元格,并且在每一个单元格内都有可能放有一石子(也有可能没有). 青蛙可以跳上石头,但是不可以跳入水中.给定石子的位置列表(用单元格序号升序表示), 请判定 ...
- [LeetCode] 403. Frog Jump 青蛙跳
A frog is crossing a river. The river is divided into x units and at each unit there may or may not ...
- Leetcode: Frog Jump
A frog is crossing a river. The river is divided into x units and at each unit there may or may not ...
- [leetcode]45. Jump Game II青蛙跳(跳到终点最小步数)
Given an array of non-negative integers, you are initially positioned at the first index of the arra ...
- 【JavaScript】Leetcode每日一题-青蛙过河
[JavaScript]Leetcode每日一题-青蛙过河 [题目描述] 一只青蛙想要过河. 假定河流被等分为若干个单元格,并且在每一个单元格内都有可能放有一块石子(也有可能没有). 青蛙可以跳上石子 ...
- Java实现 LeetCode 403 青蛙过河
403. 青蛙过河 一只青蛙想要过河. 假定河流被等分为 x 个单元格,并且在每一个单元格内都有可能放有一石子(也有可能没有). 青蛙可以跳上石头,但是不可以跳入水中. 给定石子的位置列表(用单元格序 ...
- 趣味算法——青蛙过河(JAVA)
青蛙过河是一个非常有趣的智力游戏,其大意如下: 一条河之间有若干个石块间隔,有两队青蛙在过河,每队有3只青蛙,这些青蛙只能向前移动,不能向后移动,且一次只能有一只青蛙向前移动.在移动过程中,青蛙可以向 ...
- NOIP 2005 青蛙过河
做题记录:2016-08-10 21:58:09 题目描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青蛙一次跳过的距离都 ...
随机推荐
- Vertica 分区表设计
Vertica数据库中的表只是一个逻辑概念. 实际存储在磁盘上的是projection. 当创建一张表,没有创建projection时,那么插入数据的时候会自动创建一个默认的projection.如果 ...
- 搭建了个人的github.io博客
地址:http://www.shutu.tech 说明: 基于github + hexo简易搭建的个人博客,用于收藏经典博文及技术文章,也会用于个人的技术成长记录.我是看到这篇文章搭建的:http:/ ...
- C#开发微信门户及应用(24)-微信小店货架信息管理
在前面微信小店系列篇<C#开发微信门户及应用(22)-微信小店的开发和使用>里面介绍了一些微信小店的基础知识,以及<C#开发微信门户及应用(23)-微信小店商品管理接口的封装和测试& ...
- 【C#进阶系列】27 I/O限制的异步操作
上一章讲到了用线程池,任务,并行类的函数,PLINQ等各种方式进行基于线程池的计算限制异步操作. 而本章讲的是如何异步执行I/O限制操作,允许将任务交给硬件设备来处理,期间完全不占用线程和CPU资源. ...
- 关于xml加载提示: Error on line 1 of document : 前言中不允许有内容
我是在java中做的相关测试, 首先粘贴下报错: 读取xml配置文件:xmls\property.xml org.dom4j.DocumentException: Error on line 1 of ...
- 利用Spring AOP机制拦截方法一例
直接上代码: @Aspect // for aop @Component // for auto scan @Order(0) // execute before @Transactional pub ...
- JS高程4.变量,作用域和内存问题(2)执行环境及作用域
1.执行环境:执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为, 每个执行环境都有一个与之相关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中. 2.全局执行环境: 最外围的 ...
- 【大前端之打通账号系统】passport应该如何落地?
前言 之前接入百度账号系统的时候写了一篇博客做研究:[大前端]认识单点登录,出来后才发现,很多小公司其实并没有将账号系统打通,总结一下账号系统没通的原因是: ① 最初设计就没想过身份认证应该做整合 ② ...
- kmdjs和循环依赖
循环依赖 循环依赖是非常必要的,有的程序写着写着就循环依赖了,可以提取出一个对象来共同依赖解决循环依赖,但是有时会破坏程序的逻辑自封闭和高内聚.所以没解决好循环依赖的模块化库.框架.编译器都不是一个好 ...
- 前端之HTML知识点整理
一.html概述 htyper text markup language 即超文本标记语言 超文本: 就是指页面内可以包含图片.链接,甚至音乐.程序等非文字元素. 标记语言: 标记(标签)构成的语言 ...