Leetcode做题日记:45. 跳跃游戏 II(PYTHON)

给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
你的目标是使用最少的跳跃次数到达数组的最后一个位置。

示例:

输入: [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。
从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。

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

首先理解这个说明:
也就是像这种情况,遇到0了,根本无法到达,就自动跳向下一个,跳的次数加1

在这里插入图片描述

于是,我写出了我的第一个代码:递归

	def ty(s,k,top,Top,ans):
            if top == Top: #当指标top指向最后一位
                ans.append(k) #添加跳跃次数k到跳跃数组ans中
                return
            elif top >Top: #跳过了,return
                return
            else:
                if s[0]==0: #遇到0了,自动往后跳一位,k+1
                    ty(s[1:],k+1,top+1,Top,ans)
                for i in range(1,s[0]+1): #从第一步循环到最大步长
                    if i >len(s)-1 : #如果步长大于剩余长度。return
                        return
                    ty(s[i:],k+1,top+i,Top,ans) #每次递归取nums的[i:],即剩余长度
        ans=[]    
        Top=len(nums)-1
        ty(nums,0,0,Top,ans)  
        if ans!=[]:
            return min(ans)             
        else:
            return 0

竟然超时了。
我尝试优化,大幅优化,但还是超时:

	def ty(s,k,top,Top,ans):
            if top == Top:
                ans.append(k)
                return
            elif top >Top:
                return
            elif ans and k>=min(ans): #函数添加了这一句,大幅优化
                return
            else:
                ...

我尝试修改for循环为:

		for i in range(s[0],0,-1):#从大往小,大幅优化
                    if i >len(s)-1 :
                        continue
                    ty(s[i:],k+1,top+i,Top,ans)

优化很多了,但是还是超时了
执行一个较长的代码:
在这里插入图片描述

我思考了5分钟,像这种问题,达到最min解之后,递归是停不下来的,所以非常耗时
于是换成贪心:每次计算能走到的最远的点
思路是:不需要精确的+步长到终点,只需要当前位置top+最后一步的步长大于终点的位置就能保证这一跳能达到终点

	n=nums
        k=0
        top=0
        b=0 #跳出while循环的标志位
        if len(n)==1:
            return 0
        while True:
            max_v=0
            k=k+1
            if n[top]==0: #处理0的时候
                y=1
            else:
                y=n[top]
            for i in range(1,y+1):
                if top+i>=len(n)-1:
                    b=1
                    break
                elif n[top+i]>=max_v: #选取最大值的下标
                    max_v=n[top+i]
                    m=i      
            if b==1:
                break
            top=top+m #更新   
        return k

但是当输入是[10,9,8,7,6,5,4,3,2,1,1,0]的时候,要跳10次,错误了
做一点微修改,意义是:原来是选取最大值,修改后是选取能跳的最远点的值

n[top+i]-----修改成--->n[top+i]+i
例如[2,3,1,1,4],在2这个点:
如果是n[top+i],则选取3只是因为3最大
如果是n[top+i]+i,则选取3是因为 max{1+3,2+1},i=1时能走4格最大,所以选3

最后的代码:

	n=nums
        k=0
        top=0 #记录跳点的位置
        b=0
        if len(n)==1:
            return 0
        while True:
            max_v=0 
            k=k+1
            if n[top]==0: #处理0位
                y=1
            else:
                y=n[top]
            for i in range(1,y+1): #在当前步长范围内执行for循环
                if top+i>=len(n)-1: #如果当前位置top+步长i到底,结束
                    b=1
                    break
                elif n[top+i]+i>=max_v:#选取能走的最远的点
                    max_v=n[top+i]+i
                    m=i      
            if b==1: #质朴的设置标志位跳出循环
                break
            top=top+m #更新跳点位置到能跳最远的点的位置   
        return k

44ms,排名56%

猜你喜欢

转载自blog.csdn.net/weixin_44033136/article/details/86421928
今日推荐