leetcode(55). Jump Game

来源:互联网 发布:杭州整站优化公司 编辑:程序博客网 时间:2024/05/29 19:34

problem

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.

Determine if you are able to reach the last index.

For example: A = [2,3,1,1,4], return true.

A = [3,2,1,0,4], return false.

分析

这个问题类似于 leetcode(70). Climbing Stairs,可以有两种思路,一种是从前往后的递归求解,时间复杂度应该是指数级,另一种是从后往前推算每一个位置的能否到达最后一个位置,时间复杂度为O(n2)

class Solution(object):    def canJump(self, nums):        """        :type nums: List[int]        :rtype: bool        """        n = len(nums)        if n == 0:            return True        nums[n-1] = 1        for i in range(n-2, -1, -1):            t = i + 1            m = i + nums[i]            nums[i] = 0            while t < n and t <= m:                if nums[t] == 1:                    nums[i] = 1                    break                t += 1        return nums[0] == 1

虽然相比指数级还有一些优化,但是提交还是Time Limit Exceeded,失败的案例是这样的,
[25000, 24999, 24998, …… , 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,1,0,0]
因此我又想到了一个优化的办法,由于数组内的数代表可能走出的最大步长,也就是说小于等于这个数的位置都可以走到,所以只需要保存一个当前可以到达终点的最小值即可,从后向前只需要和这个最小索引相比即可,时间复杂度为O(n),超过了50%的提交。

class Solution(object):    def canJump(self, nums):        """        :type nums: List[int]        :rtype: bool        """        n = len(nums)        if n == 0:            return True        #m表示目前已知的可以到达n-1的最小索引。        m = n-1        for i in range(n-2, -1, -1):            if num[0] >= m:                return True            if i + nums[i] >= m:                m = i        return m == 0

还看到这样一种解法,使用reach代表能走到的最大值,不断向前找看能否走到结尾,如果遇到遍历的索引大于目前能走到的最大值(即reach)的话,说明无法走到末尾。

这个算法时间复杂度也是O(n)

class Solution(object):    def canJump(self, nums):        """        :type nums: List[int]        :rtype: bool        """        n = len(nums)        reach=0        for i in range(n):            if i<= reach:                reach = max(reach, i+nums[i])                if reach >= n-1:                    return True            else:                return False        #return i==n-1 and reach>=i        return  reach>=i

总结

因为数组内的数指的是小于等于这个数的长度都可以到达,所以只需使用最小的索引来进行比较遍历时的位置能否到达结尾,将时间复杂度降为O(n)

最后一种解法是上面想法的逆向思考,上面的想的是从结尾往前找可以到达结尾的最前面的元素,这个解法是从头开始找可以到达的最远的元素reach,reach之前的元素都可以到达,它的优势在于可以在中间判定无法到达终点,而第一种总是要遍历完整个数组(即使加上if num[0] >= m:  return True也要多很多次判断)。

两种解法分析的不是太到位。

原创粉丝点击