数组跳越算法 Jump Game 的 python 代码

数组跳越算法 Jump Game 的 python 代码

题目

给定一组非负整数,起始位置是这一组非负整数的第一个整数的索引位置。
该组整数中的每一个元素代表了在该元素位置可以向前跳跃的最大步长。算法任务是以最小的步数从起始索引位置跳到最后的索引位置。
比如,给定数组 A = [2,3,1,1,4],最小的跳越次数是 2,(从0位置跳跃1步到1位置,然后跳跃3步到最后的索引位置)。

假设:一定可以从第一个索引跳跃到最后一个索引位置。

分析

题目中的假设是为了限制如果跳跃到步长为0的点,无法再向前跳跃。
其中的 for 循环是跳跃的整个过程。该过程是一个动态的过程,当 index 不断向前走时,跳跃也按照 if 控制语句向前走,最终达到终点。

其中很重要的一点是,我的代码中考虑了步长为 0 的情况,分为 以下几种情况。

1、出门起始位置即为 0,无法完成起跳,输出错误信息,can NOT jump to the last。

2、整个 for 循环完成以后,无法达到 last 索引,报错。

3、在跳跃过程中,如果 jump 的一步跳到了步长为 0 的位置,那么就要少跳一步,检查是否能够继续前进,如果能跳则继续前进,如果还是0,就还要减少一步。有一种极端情况,当jump 的步长减小到 1时,还是不能往前跳,就需要退回到上一跳,减少跳一步,检查是否可以往前跳。

例如,[2,8,1,0,0,0,0,1,4,2]这样一串数组中,如果从0开始起跳,跳到1时,再向前跳就遇到了大量的0,无法抵达终点,因此,在1位置时,需要向后退一步,返回到2位置,只向前跳一步,跳到8位置,然后一步越过大量的0,抵达终点。

但是在我的代码中,我没有考虑再向后倒退一步,因为本身 for 循环中的 index 是一直向前走的,所以如果当前跳跃中,每一步都跳到了0,直接标明无法到达终点,不再返回前一步。有需求的话可以在此基础上修改代码,使得可以完整考虑上述的例子的特殊情况。代码也不是完美的(主要是我懒得想了)
我想了一下,在数据结构中,这是一种树状遍历,其实不用树也可以,但是需要记录每一步跳跃的所有情况。这种遍历的算法复杂度我还没有想明白。当然,在面试时遇到这样的问题,往往都不考虑非负的情况,直接就假设一定可以跳到终点,那这样代码就很简单了。

代码

解释器版本 2.7.13

# -*- coding: utf-8 -*-
import random


class MinimumJumps(object):
    def __init__(self):
        pass

    @staticmethod
    def jumps(integers):
        count = 0  # 跳数计数器
        last = 0  # 上一跳可达最远距离
        reach = 0  # 向前跳可达最远距离
        list_jump = []  # 记录路径
        for index in range(len(integers)):  # jump 位置
            if last < index:  # 若索引过了上一次可达最远距离,则进行下一次跳跃,更新信息
                count += 1
                last = reach
                list_jump.append(index-1)  # 跳跃的 index 做记录,该 index 比实际列表中跳跃元素的索引大 1
            reach = max(reach, integers[index]+index-1)  # 当前最远可达位置
            index += 1
        print list_jump
        if reach < len(integers)-1 or integers[0] == 0:
            # 循环完后,最远可达位置无法到达 end , 或第一步就迈不出去
            print 'can NOT jump from the head to the last.'
            return -1
        else:
            print "the minimum steps from the start to the last is %d" % count
            for i in range(count-1):
                print "jump %d step from %d to %d" % ((list_jump[i+1]-list_jump[i]), list_jump[i], list_jump[i+1])
            a = list_jump.pop()
            print "at last, jump %d step to the last" % (len(integers)-a-1)
            return count

    @staticmethod
    def generate_list():  # 自动产生一个非负整数序列,参数自行修改
        print "generate a list of non-negative integers:"
        num = random.randint(15, 20)  # 列表长度限制在 15到 20 之间,可以改动
        list_1 = []
        for i in xrange(0, num):
            list_1.append(random.randint(0, 5))  # 步长限制在 0 到 5 之间,如果不考虑0,则上述代码一定没有问题。
        return list_1

tackle = MinimumJumps()
listing = tackle.generate_list()
print listing
a = tackle.jumps(listing)

处理结果是

generate a list of non-negative integers:
[4, 5, 4, 2, 2, 5, 4, 1, 5, 4, 0, 5, 5, 3, 3, 2]
[0, 3, 5, 9, 12]
the minimum steps from the start to the last is 5
jump 3 step from 0 to 3
jump 2 step from 3 to 5
jump 4 step from 5 to 9
jump 3 step from 9 to 12
at last, jump 3 step to the last

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值