1. 程式人生 > 其它 >【每日演算法】動態規劃五

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

目錄

918.環形子陣列的最大和

難度[中等]

給定一個由整數陣列 A表示的環形陣列 C,求 C的非空子陣列的最大可能和。

在此處,環形陣列意味著陣列的末端將會與開頭相連呈環狀。(形式上,當0 <= i < A.length時C[i] = A[i],且當i >= 0時C[i+A.length] = C[i])

此外,子陣列最多隻能包含固定緩衝區 A中的每個元素一次。(形式上,對於子陣列C[i], C[i+1], ..., C[j],不存在i <= k1, k2 <= j其中k1 % A.length= k2 % A.length)



示例 1:

輸入:[1,-2,3,-2]
輸出:3
解釋:從子陣列 [3] 得到最大和 3
示例 2:

輸入:[5,-3,5]
輸出:10
解釋:從子陣列 [5,5] 得到最大和 5 + 5 = 10
示例 3:

輸入:[3,-1,2,-1]
輸出:4
解釋:從子陣列 [2,-1,3] 得到最大和 2 + (-1) + 3 = 4
示例 4:

輸入:[3,-2,2,-3]
輸出:3
解釋:從子陣列 [3] 和 [3,-2,2] 都可以得到最大和 3
示例 5:

輸入:[-2,-3,-1]
輸出:-1
解釋:從子陣列 [-1] 得到最大和 -1

分兩種情況:

  1. 無環的情況
    此時和陣列最大子序列和的解法一樣。
  2. 有環的情況
    要使首尾兩個子區間的和儘可能的大,則中間的子區間的和應該儘可能的小,然後用陣列的總和減去最小子序列和既是首尾兩個子區間的最大值。

然後最兩種情況的最大值。其中有個特殊的情況,當最大子序列的和為負數時,則說明陣列中全部都是負數,則最大的負數就是要找的那個結果。

當陣列中都是負數時,最小的子序列和就是陣列的全部和,在第2種情況時的結果是0,在和第1種情況取最大值時的結果仍然是0,顯然不是要找的結果,因此,在找最大的子序列時,如果是負數,則可以直接返回。

class Solution(object):
    def maxSubarraySumCircular(self, nums):
        
        #假如最大的值不在環中
        n=len(nums)
        max_dp=[0]*n
        min_dp=[0]*n
        max_dp[0]=nums[0]#第一個是
        min_dp[0]=nums[0]#第一個是
        max_num=nums[0]#第一個最大
        min_num=nums[0]#第一個最小
        for i in range(1,n):
            #計算最大的
            max_dp[i]=nums[i]+max(0,max_dp[i-1])
            max_num=max(max_dp[i],max_num)
            #計算最小的
            min_dp[i]=nums[i]+min(0,min_dp[i-1])
            min_num=min(min_dp[i],min_num)

        # print(total)
        # print(max_num,max_dp)#最大值
        # print(min_num,min_dp)#最小的
        if max_num<0:
            return max_num
        total=sum(nums)#陣列中的所有數之和
        return max(max_num,total-min_num)

152.乘積最大子陣列

難度[中等]

給你一個整數陣列 nums,請你找出陣列中乘積最大的連續子陣列(該子陣列中至少包含一個數字),並返回該子陣列所對應的乘積。

示例 1:
輸入: [2,3,-2,4]
輸出: 6
解釋:子陣列 [2,3] 有最大乘積 6。

示例 2:
輸入: [-2,0,-1]
輸出: 0
解釋:結果不能為 2, 因為 [-2,-1] 不是子陣列。
class Solution(object):
    def maxProduct(self, nums):
        #因為正數乘以負數,變成小值 ;負數乘以負數,變成大值
        #所以每每次在計算一個最大值時,還需要一個小值與當前數值進行相乘,最最大的那個作為當前的最大值
        n=len(nums)
        if n<2:
            return nums[0]
        max_dp,min_dp=[0]*n,[0]*n
        max_dp[0],min_dp[0]=nums[0],nums[0]
        res=nums[0]
        for i in range(1,n):
            max_dp[i]=max(max_dp[i-1]*nums[i],min_dp[i-1]*nums[i],nums[i])
            min_dp[i]=min(max_dp[i-1]*nums[i],min_dp[i-1]*nums[i],nums[i])
            res=max(res,max_dp[i])
        return res

1567.乘積為正數的最長子陣列長度

難度[中等]

給你一個整數陣列 nums,請你求出乘積為正數的最長子陣列的長度。
一個數組的子陣列是由原陣列中零個或者更多個連續數字組成的陣列。
請你返回乘積為正數的最長子陣列長度。

示例 1:

輸入:nums = [1,-2,-3,4]
輸出:4
解釋:陣列本身乘積就是正數,值為 24 。

示例 2:

輸入:nums = [0,1,-2,-3,-4]
輸出:3
解釋:最長乘積為正數的子陣列為 [1,-2,-3] ,乘積為 6 。
注意,我們不能把 0 也包括到子陣列中,因為這樣乘積為 0 ,不是正數。
示例 3:

輸入:nums = [-1,-2,-3,0,1]
輸出:2
解釋:乘積為正數的最長子陣列是 [-1,-2] 或者 [-2,-3] 。
示例 4:

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

輸入:nums = [1,2,3,5,-6,4,0,10]
輸出:4
if f(x-1)>0 and nums[i]>0:#這個沒問題
    f(x)=f(x-1)+1
if f(x-1)>0 and nums[i]<0:
    f(x)=1
if f(x-1)<0 and nums[i]>0:
    f(x)=1
if f(x-1)<0 and nums[i]<0:#這個也沒問題
    f(x)=f(x-1)+1