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 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
Example1
[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.
Example2
[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.
解题思路
用一个哈希表来建立每个石头和在该位置上能跳的距离之间的映射,建立一个数组dp来表示在位置为i的石头青蛙的弹跳力(只有青蛙能跳到该石头上,dp[i]才大于0),由于题目中规定了第一个石头上青蛙跳的距离必须是1,为了跟后面的统一,我们对青蛙在第一块石头上的弹跳力初始化为0。虽然为0,但是由于题目上说青蛙最远能到其弹跳力+1的距离,所以仍然可以到达第二块石头。用变量k代表当前石头,如果石头i和石头k之间的距离大于在石头k上的弹跳力+1,则说明k跳不到i,k自增1,直到能跳到i的i.
遍历k和i之间的石头,如果青蛙能从中间某个石头上跳到i上,我们更新石头i上的弹跳力和最大弹跳力。这样当循环完成后,我们只要检查最后一个石头上青蛙的最大弹跳力是否大于0即可
AC代码
bool canCross(vector<int>& stones) {
unordered_map<int,unordered_set<int>>mp;
int n=stones.size();
vector<int> dp(n,0);
int k=0;
mp[0].insert(0);
for(int i=1;i<n;++i)
{
while(dp[k]+1<stones[i]-stones[k])
{
k++;
}
for(int j=k;j<i;++j)
{
int temp=stones[i]-stones[j];
if(mp[j].count(temp-1)||mp[j].count(temp)||mp[j].count(temp+1))
mp[i].insert(temp);
dp[i]=max(dp[i],temp);
}
}
return dp.back()>0;
}