LeetCode403. 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.

分析:

一道动态规划题目。这道题目的关键是找到适当的dp数组。想法也很简单,从第一块石头开始尝试着往前跳,对于一块石头上的每一个k,无非是3种可能情况(k - 1, k, k + 1)。从第一块石头开始,在每个石头上都这样尝试,看最终能否到达最后一块石头。状态d[i]是一个集合,是从前面的石头跳到第i块石头上所用的步数的集合。d[i]限定了在第i块石头上可以向前跳多少步。整个动态规划算法通过遍历一遍数组即可,时间复杂度为O(n)。

因为没有找到好的状态压缩的方式来表示在第i块石头上可以向前跳跃的步数,便用STL中的set来存储。在前几次的提交中,存储用vector,超时了。find函数是一个二分查找的函数,增加查询效率。


代码如下:beats 45.58% runtime 409ms

class Solution {
public:
    bool canCross(vector<int>& stones) {
        int size = stones.size();
        vector<set<int> > d;
        set<int>::iterator it;
        for (int i = 0; i < size; i++)
            d.push_back(set<int>());
        if (stones[1] != 1) return false;
        d[1].insert(1);
        for (int i = 1; i < size - 1; i++) {
            for (it = d[i].begin(); it != d[i].end(); it++) {
                for (int k = -1; k <= 1; k++) {
                    int index = find(stones, i + 1, stones[i] + *it + k);
                    if (index != -1) d[index].insert(*it + k);
                }
            }
        }
        return !d[size - 1].empty();
    }
    int find(vector<int>& stones, int s, int key) {
        int end = stones.size() - 1;
        int mid;
        while (s <= end) {
            mid = (s + end) / 2;
            if (stones[mid] == key) {
                return mid;
            } else if (stones[mid] > key) {
                end = mid - 1;
            } else {
                s = mid + 1;
            }
        }
        return -1;
    }
};



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值