日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

算法(27)-最大系列

發布時間:2023/12/13 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法(27)-最大系列 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最大系列

  • 1.LeetCode-239 滑動窗口的最大值
  • 2.LeetCode-53 連續子數組的最大和
  • 3.LeetCode-152 乘積最大的子數組。
  • 4.劍指 Offer 14- I. 剪繩子為k個整數段,使各個段成績最大
    • 1.dp
    • 數學推導

1.LeetCode-239 滑動窗口的最大值

窗口由左往右最大值數組Left,和由右向左最大值數組right維護。

在這里插入代碼片 def maxSlidingWindow(self, nums: 'List[int]', k: 'int') -> 'List[int]':n = len(nums)if n * k == 0:return []if k == 1:return numsleft = [0] * nleft[0] = nums[0]right = [0] * nright[n - 1] = nums[n - 1]for i in range(1, n):# from left to rightif i % k == 0:# block startleft[i] = nums[i]else:left[i] = max(left[i - 1], nums[i])# from right to leftj = n - i - 1 # i = 1, j = n-2if (j + 1) % k == 0:# block endright[j] = nums[j]else:right[j] = max(right[j + 1], nums[j])output = []for i in range(n - k + 1): # i=[0,n-k)output.append(max(left[i + k - 1], right[i]))return output

2.LeetCode-53 連續子數組的最大和

借助連續性,如果某一塊的和為負數,這一塊不會作為和最大連續子數組的開頭,因為去掉這個部分,后半段加和會更大。
動態規劃的解題思路:dp[i] 以nums[i]結尾的連續子數組的最大和,dp[i] 只與dp[i-1]有關,空間約減后,空間復雜度為0(1)

def maxSubArray(self, nums):""":type nums: List[int]:rtype: int"""res = float("-INF")dp = 0for val in nums:dp += val # [-1] 先加,更新答案,確定是否歸零res = max(dp, res)dp = max(dp, 0)return res

3.LeetCode-152 乘積最大的子數組。

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

直接思路:fmax(i)f_{max}(i)fmax?(i)表示以第i個元素結尾的乘積最大的子數組的積,狀態轉移方程為
fmax(i)=max?i=1n{f(i?1)?ai,ai}f_{max}(i)=\max_{i=1}^n\{f(i-1)*a_i,a_i\} fmax?(i)=i=1maxn?{f(i?1)?ai?,ai?}
即,fmax(i)f_{max}(i)fmax?(i)可以考慮nums[i]加入前面fmax(i?1)f_{max}(i-1)fmax?(i?1)對應的一段,或者自成一段,這兩種情況取最大值,求出所有的f_i之后,選取一個最大的作為結果。

核心問題:當前位置的最優解不一定是由前一個位置的最優解得到。因為存在正負數

如果當前的數是負數的話,我們希望以num[i-1]為結尾的某一個段的積也是一個負數,負負可以為正。

如果當前數為正,我們希望以num[i-1]為結尾的某一個段的積也是一個正數,正的越多,乘積完越大。

所以再維護一個fmin(i)f_{min}(i)fmin?(i)表示以第i個元素結尾的乘積最小的子數組的積:
fmax(i)=max?{fmax(i?1)?ai,fmin(i?1)?ai,ai}fmin(i)=min?{fmax(i?1)?ai,fmin(i?1)?ai,ai}f_{max}(i)=\max\{f_{max}(i-1)*a_i,f_{min}(i-1)*a_i,a_i\}\\ f_{min}(i)=\min\{f_{max}(i-1)*a_i,f_{min}(i-1)*a_i,a_i\}fmax?(i)=max{fmax?(i?1)?ai?,fmin?(i?1)?ai?,ai?}fmin?(i)=min{fmax?(i?1)?ai?,fmin?(i?1)?ai?,ai?}

def maxProduct(self, nums):""":type nums: List[int]:rtype: int"""pre_max, pre_min = 1, 1res = float("-INF")for val in nums:cur_max = max(pre_max * val, pre_min * val, val)cur_min = min(pre_max * val, pre_min * val, val)pre_max, pre_min = cur_max, cur_minres = max(res, cur_max)return res

4.劍指 Offer 14- I. 剪繩子為k個整數段,使各個段成績最大

給你一根長度為 n 的繩子,請把繩子剪成整數長度的 m 段(m、n都是整數,n>1并且m>1),每段繩子的長度記為 k[0],k[1]…k[m-1] 。請問 k[0]k[1]…*k[m-1] 可能的最大乘積是多少?例如,當繩子的長度是8時,我們把它剪成長度分別為2、3、3的三段,此時得到的最大乘積是18。

1.dp

dp[i]: 長度為i 繩子至少剪了一次的最長長度
dp[i]=max(dp[j]?(i?j),j?(i?j),dp[i]),j∈[1,i?1]dp[i] = max(dp[j]*(i-j),j*(i-j),dp[i]),j\in[1,i-1]dp[i]=max(dp[j]?(i?j),j?(i?j),dp[i]),j[1,i?1]

class Solution(object):def cuttingRope(self, n):""":type n: int:rtype: int"""dp = [0]*(n+1)dp[1] = 1for i in range(2,n+1):for j in range(1,i):dp[i]= max(dp[i],dp[j]*(i-j),j*(i-j))return dp[-1]

n^2復雜度的DP

數學推導

通過數學不等式推到,可以得到,當每段長度為3時乘積最大。所以盡可能分為三段,最后一段依據具體情況判斷:

class Solution(object):def cuttingRope(self, n):""":type n: int:rtype: int"""if n<=3:return n-1s, mod = n //3, n % 3 if mod == 0:res = 3**selif mod == 1:res = 3**(s-1)*4 else:res = 3**s*2return res%(10**9+7)

總結

以上是生活随笔為你收集整理的算法(27)-最大系列的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。