【每日演算法】動態規劃四

Hitechr 發表於 2021-09-08
演算法

53.最大子序和

難度[簡單]

給定一個整數陣列 nums ,找到一個具有最大和的連續子陣列(子陣列最少包含一個元素),返回其最大和。

示例 1:
輸入:nums = [-2,1,-3,4,-1,2,1,-5,4]
輸出:6
解釋:連續子陣列 [4,-1,2,1] 的和最大,為 6 。
示例 2:

輸入:nums = [1]
輸出:1
示例 3:

輸入:nums = [0]
輸出:0
示例 4:

輸入:nums = [-1]
輸出:-1
示例 5:

輸入:nums = [-100000]
輸出:-100000

定義f(x)為前x項的子序列的最大和

if f(x-1)<0 and nums[x]>0:
    f(x)=nums[x]
if f(x-1)<0 and nums[x]<0:
    f(x)=nums[x]#如果都是負數,則當前數就是最大的
if f(x-1)>0 and nums[x]>0:
    f(x)=f(x-1)+nums[x]
if f(x-1)>0 and nums[x]<0:
    f(x)=nums[x]#前x-1項都是正數,當前數為負數,則需要重新計算
因此,if f(x-1)<0 or nums[x]<0:
        f(x)=nums[x]
      else:# f(x-1)>0 and nums[x]>0
        f(x)=f(x-1)+nums[x]

可以推到出遞推公式為:dp[i]=max(dp[i-1],0)+nums[i]
定義初始值dp[0]=nums[0]

class Solution(object):
    def maxSubArray(self, nums):
        n=len(nums)
        dp=[0]*n
        dp[0]=nums[0]
        # dp[i]=max(dp[i-1],0)+nums[i]
        for i in range(1,n):
            dp[i]=max(dp[i-1],0)+nums[i]
        return max(dp)

55.跳躍遊戲

難度[中等]

給定一個非負整數陣列 nums ,你最初位於陣列的 第一個下標 。
陣列中的每個元素代表你在該位置可以跳躍的最大長度。
判斷你是否能夠到達最後一個下標。

示例 1:
輸入:nums = [2,3,1,1,4]
輸出:true
解釋:可以先跳 1 步,從下標 0 到達下標 1, 然後再從下標 1 跳 3 步到達最後一個下標。

示例 2:
輸入:nums = [3,2,1,0,4]
輸出:false
解釋:無論怎樣,總會到達下標為 3 的位置。但該下標的最大跳躍長度是 0 , 所以永遠不可能到達最後一個下標。

從頭開始遍歷,按每個座標和對應的值跳到下個,然後從下個繼續按座標和值往後跳,如果能跳到超過陣列的最大長度,則可以跳到最後一個位置

class Solution(object):
    def canJump(self, nums):
        jump_max=0
        for i,v in enumerate(nums):
            if i>jump_max:
                return False
            jump=i+v
            jump_max=max(jump,jump_max)
            # print(jump,jump_max)
        return True

45.跳躍遊戲II

難度[中等]

給你一個非負整數陣列 nums ,你最初位於陣列的第一個位置。
陣列中的每個元素代表你在該位置可以跳躍的最大長度。
你的目標是使用最少的跳躍次數到達陣列的最後一個位置。
假設你總是可以到達陣列的最後一個位置。

示例 1:

輸入: nums = [2,3,1,1,4]
輸出: 2
解釋: 跳到最後一個位置的最小跳躍數是 2。
     從下標為 0 跳到下標為 1 的位置,跳 1 步,然後跳 3 步到達陣列的最後一個位置。
示例 2:

輸入: nums = [2,3,0,1,4]
輸出: 2

定義f(i,j)為從i到j所需的最小跳躍數
dp[end] =min(dp[end],dp[start]+1)

相關文章