LeetCode(55 跳跃游戏II)

博客讨论了LeetCode第55题‘跳跃游戏II’的解决方案,从最初的递归思路出发,分析其效率问题。接着提出通过记录已走过的位置来避免重复运算,从而优化递归解法。最后,实现了一个无需递归的循环解法,显著提高了效率。

如题在这里插入图片描述
一眼看上去最直观肯定就是递归了,那就安排

public static boolean canJump(int[] nums) {
		if(nums==null||nums.length==0) {
			return false;
		}else if(nums.length==1) {
			return true;
		}
        return canJum(nums,0);
    }
	
	public static boolean canJum(int[]nums,int i) {
		int num=nums[i];
		if(i+num>=nums.length-1) {   
			return true;
		}
		if(num==0) {
			return false;
		}
		boolean b=false;
		for(int m=1;m<=num;m++) {   
			b=b||canJum(nums,i+m);
		}
		return b;
	}	

很直观的写法,也是不出意外的结果在这里插入图片描述
很显然,当中做了很多的重复运算,那么我们是否可以去除这些重复运算呢,很显然可以的

public static boolean canJum1(int[]nums,int i) {
		int num=nums[i];
		if(i+num>=nums.length-1) {
			return true;
		}
		if(num==0) {
			return false;
		}
		nums[i]=0;     //第一次参与运算后归0 后续可直接退出
		boolean b=false;
		for(int m=1;m<=num;m++) {
				b=b||canJum(nums,i+m);
			}
		return b;
	}

好了,可以通过了在这里插入图片描述
但是这个效率肯定不行。既然已经想到记录已经走过的点,那么不用递归也能实现啊。譬如nums[0]=3;那么一直到0,可达的最大index为0+3。然后我们对1到3范围进行判断,假设其中nums[2]=3,2+3为该段最大值,那么我们就重复判断起始3,最大5的段。退出条件很显然,可达>=nums的最大index,期间若是起始index与最大可达相等,则为无法继续向后跳转。

public static boolean canJump2(int[] nums) {
		if(nums==null||nums.length==0) {
			return false;
		}
		int st = 0;		//某一段起始index
		int max = st+nums[st];   //到到此index时可达的最大index
		if(max>nums.length-1) {			
			return true;
		}
		while (max>st) {
			int m=max; 
			for(int i =st+1;i<=m;i++) {		//对于当前段进行遍历,更新可达
				max=Math.max(max, i+nums[i]);
			}
			if(max>=nums.length-1) {  
				return true;
			}
			st=m;
		}
		return false;
	}

结果在这里插入图片描述
大大进步了,但是还能进一步,既然关注的是可达的最大index,并不需要分段,那么很显然的可以直接循环实现

public static boolean canJump3(int[] nums) {
		if(nums==null||nums.length==0) {
			return false;
		}
		int max = nums[0];   //可达index
		for(int i=0;i<=nums.length-1;i++) {
			if(max>=nums.length-1) {
				return true;
			}else if(max<i) {    //前序可达小于当前index,即当前index不可达
				return false;
			}
			if(i+nums[i]>max) {
				max=i+nums[i];
			}
		}
		return true;
	}

结果可以了
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值