给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
你的目标是使用最少的跳跃次数到达数组的最后一个位置。
示例:
输入: [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%