Jump Game

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

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

Determine if you are able to reach the last index.post

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

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

這是Jump Game系列的第一題,判斷根據給出的數組能不能到達最後一個index。若是能夠的話,則返回True。code

使用DP的話,設f(i)表示爲可否到達index爲i的位置。分解子問題則 f(i) = OR(f(j) and j + A[j] > i)即若是小於i的index j上若是跳一步能夠到達i, 則i能夠到達。根據這個給出DP的代碼以下:htm

class Solution(object):
    def canJump(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        if not nums:
            return true
        n = len(nums)
        res = [False]*n
        res[0] = True
        for i in xrange(1,n):
            for j in xrange(i,-1,-1):     #倒序,能夠減小遍歷的次數
                if res[j] == True and nums[j]+j>=i: #剪枝,防止超時。 res[i] = True break
        return res[-1]

注意由於有多種可能的路徑,因此一旦找到使OR爲真的j,就須要進行剪枝。不然DP的複雜度就是O(n^2),在Leetcode上會超時。blog

這一題最優的解法爲貪心,O(n)。作法是維護一個在index i時可到達的最遠距離reach,這個reach不必定是在index i處跳nums[i]到達的,能夠是在i以前的index上到達的,是一個歷史最優。element

1.能繼續循環,處理到i的條件爲i<=reach。即i處在歷史可到達的最遠距離範圍中。get

2.reach的更新是 reach = max(reach,i+nums[i]).

3.判斷能夠達到終點的條件是reach>= len(nums)-1.

由於每一步維護的是一個局部最優解,因此是貪心的解法,代碼以下:

class Solution(object):
    def canJump(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        if not nums:
            return True
        reach, i = 0, 0 
        while i <= reach and reach < len(nums):
            reach = max(reach,nums[i]+i)
            i = i+1
        return reach >= len(nums)-1

空間複雜度也爲O(n)。

上述這種解法也能夠認爲是DP,和Maximum Subarray很是相似,能夠認爲咱們維護了一個local最優,即當前位置能夠跳到的最遠距離:nums[i]+i,全局最優:歷史位置上能夠到達的最遠距離:即reach.每次更新局部最優時,同步更新全局最優。

相關文章
相關標籤/搜索