3.3 跳跃问题(Jump Game)
3.3.1 问题描述
给定一个非负整数数组,初始状态你在数组的第一个位置。数组中的每个元素代表你在该位置可以跳跃的最大长度。请判断,你最后是否能够抵达最后一个位置?
3.3.2 暴力求解
算法思路:设置一个新数组,遍历原数组,把元素能到达的位置都在新数组里标为1,最后看最后一位是否为1。
算法实现
1 | public boolean canJump(int[] nums){ |
时间复杂度:O(mn)
,n为元素组的元素个数,m为数组内元素值的最大值,也就是每次走的步数的最大值。
缺陷:子问题存在重复地判断或写入1,导致速度变慢。
3.3.3 动态规划
算法思路:如果第i个元素可以到达终点,则在它之前的元素,只要能到达i,就必然能到达终点。本着这个原则,我们把数组的后面往前看,逐个遍历数组元素,如果某个元素可以到达终点,就把它设置为终点,看在它前面的元素能不能到达这里。这样就形成了一个新的子问题,这个子问题跟原问题是一样的。所以我们使用递归的方法实现。
动态规划的思想
- 问题分阶段(Multiple stage):每个子问题的递归就是分阶段的体现
- 阶段有依赖(Optimal sub-structure):每一个子问题的都有一个前提,即依赖条件,就是子问题的终点能够到达父问题的终点
- 依赖有重叠(Overlapping sub-problem):我们解决了暴力求解中存在的重复操作
代码实现
1 | public boolean canJump(int[] nums){ |
时间复杂度:Θ(n)
3.3.4 解法三
算法思路:如果数组元素全为正数,则必然可以到达终点。所以问题的本质在于是否可以走过值为0的元素。
代码实现
1 | public boolean canJump(int[] nums){ |