LeetCode题解(Week 8):403. Frog Jump

本文探讨了一只青蛙如何跨越河流的经典问题。青蛙从第一块石头出发,每一步只能向前跳,且跳跃的距离受到前一步跳跃距离的限制。文章提供了一个算法解决方案,利用动态规划的方法判断青蛙是否能成功到达最后一块石头。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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.

中文大意

经典的青蛙过河问题,有一个数组a={a1,a2,a3…,an},其中a1 = 0, 一只青蛙从a1出发,第一步走1个单位,青蛙过河有这样的规律:第k-1次如果跳了n个单位,那么第k次就只能跳n,n-1,n+1个单位,并且只能向前跳,问青蛙能否到达对岸(也就是跳到an)

题解

class Solution {
public:
    bool canCross(vector<int>& stones) {
        int n = stones.size();
        unordered_map<int, unordered_set<int>> dp;
        dp[0].insert(0);

        int maxdist = 0;
        for(int i = 1 ;i < n;i++)
        {
            for(int j = 0;j<i;j++)
            {
                int currdist = stones[i] - stones[j];
                //如果跳maxdist+1跳不到现在的这个石头,那就不用考虑j这块石头了
                if(currdist > maxdist+1) continue;
                if(dp[j].count(currdist)||dp[j].count(currdist-1)||dp[j].count(currdist+1))
                {
                    dp[i].insert(currdist);
                    maxdist = max(currdist,maxdist);
                }
            }
        }

        return dp[n-1].size() > 0;
    }
};

思路

又是典型的动态规划问题了,状态分解的思路如下,记:

  • dp[i]等于“从上一块石头(不一定是i-1)跳到第i块石头,跳了多少步”
  • dist = stone[i] - stone[j]表示石头i与石头j之间的距离

这个时候,dp[i]可以通过dist以及dp[0…i-1]来得到:

  • 如果dp[j]其中(0 <= j < i) 的值刚好为dist,意味着青蛙可以从j跳dist个单位到达i,dp[i] = dist
  • 同理,如果dp[j]=dist-1,意味着青蛙可以从j跳dist个单位到达i,dp[i] = dist
  • 同理,有dp[j]=dist+1,dp[i] = dist

但是到达i的方式不唯一(可能存在多个j能够跳到i),因此需要用一个特定的结构(比如集合),将dp[i]中的每一个可能取值都存起来

但是!这样做是会超时的,因为时间复杂度不符合题目的要求,解决方法是通过一个数maxdist,来记录下当前青蛙跳过的最长距离,如果当前的距离dist(i,j)比这个最长距离加一还要大的话,意味着肯定不能从j跳到i了,直接continue

这样做的话,时间复杂度是O(n^2),空间复杂度接近O(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值