【LeetCode】45、跳跃游戏Ⅱ(动态规划)

题目描述

给定一个非负整数数组,你最初位于数组的第一个位置。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

你的目标是使用最少的跳跃次数到达数组的最后一个位置。

示例

在这里插入图片描述

说明

假设你总是可以到达数组的最后一个位置。

解题思路

刚开始想到的思路是递归,调用递归函数(参数携带表示位置的索引)返回从该位置到最后一个位置需要的最小跳数。
虽然递归法可以求解,但这并不是一个好的思路。不管是从时间还是空间来说消耗都非常大,时间复杂度是指数增长的,调用过多的递归函数会占用很多内存,而且如果数组长度到15以上或者20以上,递归法都会超时。
然后想到了一个好的思路是动态规划,这道题的描述和构造非常适合使用动态规划求解。第一个位置到最后一个位置的最小跳跃数,不妨构造一个数组表示每个位置到最后一个元素的最小跳跃数,从最后依次往前写入数据,直到写到第一个位置(到最后一个位置)的最小跳跃数。
从后往前写入每个位置到最后一个位置的最小跳跃数,初始化将最后一个位置的跳跃数置0,从倒数第二个位置开始向前遍历。该位置如果能直接跳到最后一个位置(该位置索引+该位置跳跃最大长度 大于或等于 最后一个位置的索引),则该位置最小跳跃数为 1;如果不能跳到最后一个位置,则该位置最小跳跃数为 他所能跳到的所有位置中最小跳跃数最小的值 加1。这样依次向前遍历,直到索引 i=0结束。得到第一个位置到最后一个位置的最小跳跃数。

动态规划代码

#include<vector>

class Solution {
public:
    int jump(vector<int>& nums) {
		int leng = nums.size();
		int *p = new int[leng];	//p数组记录每个位置到最后一个位置的最小跳数 
		
		p[leng-1]=0;	//初始化最后一个位置的跳数为0 
		for(int i=leng-2;i>=0;i--)	 
		{
			if(nums[i]==0)
				p[i]=leng+1;
			if(nums[i]+i>=leng-1)	//如果自己能直接到达最后
			{
				p[i]=1;
			}else{			//如果自己不能到最后 
				int min=p[i+1];
				int index=i+1;
				while(index<=i+nums[i]){
					if(p[index]<min)
						min=p[index];
					index++;
				}
				p[i]=min+1;		//该位置的最小跳数等于 --》他能到达的所有位置中跳数最小的+1 
			}
		} 
		return p[0]; 
    }
};

递归法(不是一个好方法)

#include<vector>

class Solution {
public:
	//返回在该节点跳跃到最后一个节点需要跳跃的最小次数 
    int dfs(vector<int>& nums,int index){
    	if(index==nums.size()-1)	//如果到最后一个节点,返回 1 
    		return 0;	//最后一步算0,前面每跳一步+1(因为最开始idnex=0算一步,结尾times+1) 
        if(index>=nums.size()||nums[index]==0)
        	return nums.size()+1;	//返回一个很大的数
		int max = nums[index];		//当前能跳跃的最大步数
		
		int times = nums.size()+1;	//设置最小跳跃次数 
		for(int i=1;i<=max;i++)
		{
			int rs = dfs(nums,index+i);
			
			if(rs<times)
				times = rs;
		} 
		
		return times+1;
    }
    
    int jump(vector<int>& nums) {
		// index表示当前索引,times表示跳跃次数
		int index = 0;
		int times = 0;
		int result = dfs(nums,index); 
		
		return result; 
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值