算法设计与分析:Jump Game II(Week 7)

学号:16340008

题目:Jump Game II


Question:

Given an array of non-negative integers, you are initially positioned at the first index of the array.

Each element in the array represents your maximum jump length at that position.

Your goal is to reach the last index in the minimum number of jumps.

Example:

Input: [2,3,1,1,4]
Output: 2
Explanation: The minimum number of jumps to reach the last index is 2.
    Jump 1 step from index 0 to 1, then 3 steps to the last index.

Note:

You can assume that you can always reach the last index.


Answer:

 题目是从Greedy分类中找到的。题意为:给一串非负数组num,从下标0开始,每次能从第i位最多跳num[i]步,到第i+num[i]位,求从下标0开始跳若干次到数组末尾所用的最少步数。起初的思路并没有贪心算法的思想。算法如下:

  1. 创建数组steps,以及变量 i, j = 0
  2. 判断nums[i],若非0则刷新steps[i+1]到steps[i+nums[i]+1]的最小步数(step[i]+1与原值之间取最小值)
  3. 重复步骤2,直到 i + nums[i] + 1 == sizeof(num) - 1

这个算法省略了一些细节,但主要思路就是遍历数组nums的每个值,并不断修正其能到达的位置的最小步数,直到能到达尾部。算法的时间复杂度最低能到O(1),但是当数组情况特殊时,即除了最后一步,每一步都最远都只能去到末尾前一位时,复杂度将是O(n^2)。初步代码如下(python3):

class Solution:
    def jump(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        n = len(nums)
        if n == 1 or n == 0:
            return 0
        steps = [0] * n
        for i in range(n):
            for j in range(nums[i]):
                if i + j + 1 >= n:
                    break
                if i + j + 1 == n - 1:
                    return steps[i] + 1
                if steps[i+j+1] == 0:
                    steps[i+j+1] = steps[i] + 1
                else:
                    steps[i+j+1] = min(steps[i+j+1], steps[i] + 1)

本地测试代码如下:

test = Solution()
nums = [2,3,1,1,4]
print(test.jump(nums))

 然而提交时遇到了TLE:

这里便是上文提到的极端情况。上面的算法实际上有很多不需要的计算,例如到不必经过的位的步数计算,以及不同起跳点到同一位置的重复运算。由于题目是贪心算法分类的,于是从贪心算法的思想入手。贪心算法需要考虑当前的每个选择的价值,总是做出在当前看来是最好的选择。然而显然单纯的每次跳最远并不是最佳的(如[3,5,5,1,1,1,1]),因此我们对每个选择的优劣要有更远的判断。对当前能到的每个位置而言,所选的位置下一步能跳到最远的那一个(不是该位置能跳的距离最远,而是落地点相比较),即是最优的选择。假设选择A的下一步能跳到最远,任何其他选择中的其中一个选择B的下一步能到的位置要消耗1步,而A到这些位置也是1步,但A比B远的部分,B要2步或更多,A仍然是1步。因此核心算法如下:

  1. 对nums[i],如果nums[i]+i >= length,则返回step
  2. 遍历nums[i+1]到nums[i+nums[i]],以上述方法选出最优位置nums[j],step++,以nums[j]作为标准重复1,2步

代码如下(python3):

class Solution:
    def jump(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        n = len(nums)
        if n == 1 or n == 0:
            return 0
        step = 0
        i = 0
        while i < n:
            step += 1
            if nums[i] + i >= n - 1:
                return step
            maxI = 0
            temp = 0
            for j in range(nums[i]):
                if maxI < nums[i + j + 1] + j:
                    maxI = nums[i + j + 1] + j
                    temp = j
            i += temp + 1

 最终优化效果理想:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值