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.

一个青蛙想要跳过河,河被分成x个单元,每个单元上可能存在着石头,青蛙只可以跳到这些石头上。现在给定一个递增的序列,代表石头的位置,判断青蛙能否跳到最后一个石头上。青蛙初始只能跳1个单元的距离,如果上一次起跳的距离为K,那么下一次起跳距离的为k-1,k或者k+1。青蛙只能向前跳。

思路:由于每次跳的长度只有3个可能,很容易可以想到通过枚举的方法列出所有可能判断能不能跳过去,通过暴力搜索的方法。但是这样做会超时,可以在搜索的时候用二分查找或者用将vector储存换成hash table储存提高搜索效率。显然,这并不是最好的解决方法。其实就是一个明显的dynamic programming的问题,刚好老师这星期就讲了这种类型的题目,对这道题目就迎刃而解了。用一个大小为n的数组代表每一个石头,再用n个set记录第i个石头能到达的石头集合,比如dp[0]的set为{1},因为从起点出发只能跳到距离为1的第一个单元上。遍历每一个石头a,对这个石头后面的每一个石头b检查一遍,计算之间的距离h。当前遍历的石头a对应有一个集合,是能直接跳到的石头的距离的集合,将集合里的距离与a和b之间的距离h进行比较,如果距离大于h+1,则继续搜索,因为序列是递增的,下一个距离肯定会变小。如果距离小于h-1,则停止搜索,因为下一个距离会更加小,不可能跳到比h-1还小的距离。如果距离在[h-1,h+1]之间,则说明可以跳到这个石头b,在石头b的集合insert这个距离。遍历完所有的石头之后,只要检查第n个石头的集合是不是空的就可以判断能不能跳到第n个石头了。

class Solution {
public:
    bool canCross(vector<int>& stones) {
        if(stones[1] != 1) return false;//特殊情况判断
        int n = stones.size();
        vector<set<int>> dp(n);//二维数组记录能跳到的石头集合
        dp[0].insert(1);
        for(int i = 0; i < n; ++i)
        {
            for(int j = i+1; j < n; ++j)
            {
                int step = stones[j] - stones[i];//求出两个石头的实际距离
                for(set<int>::iterator it = dp[i].begin(); it != dp[i].end(); ++it)
                {
                    if(*it+1 < step)//如果距离大于k+1,继续搜索
                        continue;
                    if(*it-1 > step)//如果距离小于k-1,停止搜索
                        break;
                    dp[j].insert(step);//把能跳到的距离加入到集合

                }
            }
        }
        if(!dp[n-1].empty())
            return true;
        else
            return false;
    }
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值