Leetcode-跳跃游戏I和II(动态规划)

目录

存在型动态规划

第一步:确定状态

最后一步:

子问题

结合最后一步与子问题确定状态的定义

确定状态转移方程

第二步:确定初始条件和边界条件

第三步:确定计算顺序

代码实现

最大/小型动态规划

第一步:确定状态 

最后一步

子问题

确定状态

确定状态转移方程

第二步:确定初始条件和边界

第三步:计算顺序

代码实现


Leetcode.55-跳跃游戏

 这题可以用贪心来写,但是还是为了学习动态规划,从动态规划的角度去写。

存在型动态规划

判断是否存在结果

第一步:确定状态

从最后一步分析子问题,以确定状态

最后一步

当可以跳跃到最后一个位置n-1时,考虑是从位置i跳跃到n-1的位置。

i<n-1,且i+nums[i]>=n-1

从最后一步分析,要存在跳跃到最后一个位置的情况,满足两个条件

  1. 可以存在跳跃到位置i
  2. 最后一步不超过跳跃的最大距离i+nums[i]

子问题

从最后一步推出的子问题:能不能跳跃到位置i

结合最后一步与子问题确定状态的定义

状态:f(i)-能不能跳跃到位置i

确定状态转移方程

f(i)=OR< 0<=j<i >(f(j)&&j+nums[j]>=i)

要将位置i之前的所有位置都要判断一遍,只要存在一个满足条件,那么就能到达位置i

第二步:确定初始条件和边界条件

刚开始是从位置0开始跳跃,且,位置0跳跃到位置0的情况是可行的,所以f(0)=1

最后一个位置就是f(n-1),也就是问题的返回结果

第三步:确定计算顺序

由于要计算f(i),需要将i之前的所有下遍都进行计算,所有不仅仅要从0遍历到n01,还需要再来一个内循环遍历,从0到i-1去遍历,这样才能找出满足条件的情况,由于在leetcode中内循环从0向后遍历会超时,所有变成从后向前遍历,可以通过。

时间复杂度O(N^2),空间复杂度O(N)

代码实现

class Solution {
public:
    bool canJump(vector<int>& nums) {
        int len=nums.size();
        int* arr=new int[len];
        arr[0]=1;
        for(int i=0;i<len;i++)
        {
            if(i==0)
            {
                continue;
            }
            arr[i]=0;
            for(int j=i-1;j>=0;j--)
            {
                if(arr[j]&&nums[j]+j>=i)
                {
                    arr[i]=1;
                    break;
                }
            }
            
        }
        return arr[len-1];
    }
};

最大/小型动态规划

Leetcode.45-跳跃游戏II

本题同样用贪心实现的话,更为简单,快捷。

从动态规划的角度去解题

本体要求解从0位置跳跃到n-1位置的最少跳跃次数,符合最大最小问题

第一步:确定状态 

从最后一步分析,以得到一个递归的关系

最后一步

从位置i跳跃到位置n-1,那么就是最少的跳跃次数到位置i+1就可以得到跳跃到n-1的位置。

如果假设位置i是最少跳跃次数到位置n-1的情况的前一步,那么下一步该分析的是跳跃到i位置的最少次数是多少。

子问题

跳跃到i位置的最少次数

确定状态

f(i):跳跃到位置i的最少跳跃次数

确定状态转移方程

f(i)=min{< 0<=j<i >( f(j)+1 )}

位置i之前的位置都需要去寻找判断,还需要满足条件j+nums(j)>=i

第二步:确定初始条件和边界

最开始肯定是从位置0开始向后跳跃。且,位置0肯定是可以到达的,设置最少跳跃次数为0,不需要跳跃

第三步:计算顺序

由于要计算f(i),需要将i之前的所有下遍都进行计算,所有不仅仅要从0遍历到n01,还需要再来一个内循环遍历,从0到i-1去遍历,这样才能找出满足条件的情况,由于在leetcode中内循环从0向后遍历会超时,所有变成从后向前遍历,可以通过。

由于判断最少次数,可以初始设值为INT_MAX,然后去内循环中依次比骄傲最小值,比较前要判断是否符合到达i位置的条件

时间复杂度O(N^2),空间复杂度O(N)

代码实现

class Solution {
public:
    int jump(vector<int>& nums) {
        int len = nums.size();
        int* arr=new int[len];
        arr[0]=0;
        for(int i=1;i<len;i++)
        {
            int minnum=INT_MAX;
            for(int j=i-1;j>=0;j--)
            {
                
                if(j+nums[j]>=i)
                {
                    minnum=min(minnum,arr[j]+1);
                }
            }
            arr[i]=minnum;
        }
        return arr[len-1];
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值