給定一個整數陣列,找出總和最大的連續數列,並返回總和。
題目:給定一個整數陣列,找出總和最大的連續數列,並返回總和。
這個題目初看不會,看了解答還是不會,又看了解答終於想明白了,關鍵點就一個 連續數列
什麼叫做連續數列,就是連在一起的資料。
例如有一個數列,我們要找其中連續的子序列,假設-1是我們最大連續子序列的最後一個數字,然後我們求出以這個數字為結尾的所有的連續的子序列,然後把每一個子序列求和
最後元素 | 後 | 面 | 不 | 管 | 子序列和 | |||||
---|---|---|---|---|---|---|---|---|---|---|
原始序列 | -2 | 1 | -3 | 4 | -1 | 2 | 1 | -5 | 4 | |
子序列1 | -1 | -1 | ||||||||
子序列2 | 4 | -1 | 3 | |||||||
子序列3 | -3 | 4 | -1 | 0 | ||||||
子序列4 | 1 | -3 | 4 | -1 | 1 | |||||
子序列5 | -2 | 1 | -3 | 4 | -1 | -1 |
然後我們再假設2是最大連續子序列的最後一個元素,再來求一遍每個子序列的和
最後元素 | 面 | 不 | 管 | 子序列和 | ||||||
---|---|---|---|---|---|---|---|---|---|---|
原始序列 | -2 | 1 | -3 | 4 | -1 | 2 | 1 | -5 | 4 | |
子序列1 | 2 | 2 | ||||||||
子序列1 | -1 | 2 | 1 | |||||||
子序列2 | 4 | -1 | 2 | 5 | ||||||
子序列3 | -3 | 4 | -1 | 2 | -2 | |||||
子序列4 | 1 | -3 | 4 | -1 | 2 | 3 | ||||
子序列5 | -2 | 1 | -3 | 4 | -1 | 2 | 1 |
有點感覺了吧,這其實就是把所有連續的子序列全部羅列一邊,然後求出所有的連續的子序列的和。
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
if nums == []:
return 0
dp = []
for end in range(1 ,len(nums)):
for start in reversed(range(end+1)):
dp.append(sum(nums[start:end])+nums[end])
return max(dp + nums)
同樣的我們也可以以某個元素為開始計算連續子序列的和。
動態規劃
緊接著就是我們的動態規劃出場了,其實有點經驗的人看到這個題目就知道使用動態規劃,只是轉移方程不會寫。
加入我們已經知道以第i-1為結尾的最大子序列和
dp[i-1] | dp[i] | 子序列和 | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
原始序列 | -2 | 1 | -3 | 4 | -1 | 2 | 1 | -5 | 4 | |
子序列1 | -2 | 1 | -3 | 4 | -1 | 3 | ||||
子序列2 | -2 | 1 | -3 | 4 | -1 | 2 | 5 |
因為是連續的(包含nums[i]以及前面的)所以直接可以知道dp[i] = dp[i-1]+nums[i],這裡有一個很有趣的地方
dp[i-1] | nums[i] | 要不要加上 |
---|---|---|
正 | 正 | 都是正的加上肯定變大啊,跟前面的子序列連上變成更長的子序列 |
正 | 負 | 前面是正的,趕快加上前面的連續子序列,讓自己變的大一點 |
負 | 負 | 本來就是負的了,再加上dp[i-1]的負數就更小了,不加,獨立門戶,自己就是連續子序列 |
負 | 正 | 自己是正的,為什麼要跟前面的負數連在一起,獨立門戶,自己就是連續子序列 |
哈哈,我們們的轉移方程就出現了,加上去比自己大,那就加上,如果加上去比自己還小了,肯定就不加了啊
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
if nums == []:
return 0
for i in range(1 ,len(nums)):
nums[i] = max(nums[i-1]+nums[i],nums[i])
return max(nums)
這個問題還可以更精簡,如果前面是正的,我們們就加上,如果前面是負的,那麼當前的最大子序列和就是自身nums[i]
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
if nums == []:
return 0
res,s = -float('inf'),0
for v in nums:
s += v
res = max(res,s)
if(s < 0): s = 0
return res
分治法
其實做這個題目我就是想要學習一下分治演算法,沒想到前面寫了這麼多。分治求解的思想非常的簡單,我們的連續子序列有三種可能
- 和最大的子序列存在我們整個序列的左側
- 和最大的子序列存在我們整個序列的左側
- 橫跨序列左半部分和右半部分:也就是說,中間這個數字是左邊子序列的結尾,是右邊子序列的開始,我們算一下以這個數字開始和結尾的左右子序列最大和,然後求和即可,說起來有點繞,看圖
比較三者的大小,最大者即為所求的最大子序列和
左邊 | 中間 | 右邊 | 最大和 |
---|---|---|---|
最大子序列子這邊 max_left | max_left | ||
以v結尾的和最大的子序列 max_v_left | v | 以v開始的和最大的子序列 max_v_right | max_v_left + v + max_v_right |
最大子序列子這邊 max_right | max_right |
整體就是這個樣子的,然後我們們寫一個虛擬碼試試
def maxSubArray(nums):
l,r = 0,len(nums)
mid = (l+r) // 2
# 最大和子序列在左側
max_left = maxSubArray(nums[:mid])
# 最大和子序列在右側
max_right = maxSubArray(nums[mid:])
# # 最大和子序列兩側都包含元素
# 首先計算以mid為結尾的左側最大子序列的和,這個最開始的那種方法一模一樣啊
# 即,一個一個元素增加求每一個子序列的和
left_res,right_res = 0,0
left_max,rigth_max = -float('inf'),-float('inf')
# 以mid結束的前面所有連續子序列的和,求其中的最大(這裡是去除了mid的值,要不然這裡會被計算一次)
for v in reversed(nums[:mid]):
left_res += v
left_max = max(left_max,left_res)
# 以mid開始的前面所有連續子序列的和,求其中的最大 (然後這裡還會被計算一次,所以上面去掉了mid)
for v in nums[mid:]:
right_res += v
rigth_max = max(rigth_max,right_res)
max_mid = left_max + rigth_max
return max(max_left,max_right,max_mid)
相關文章
- 給定一個整數陣列 nums 和一個目標值 target,請你在該陣列中找出和為目標值的那 兩個 整數,並返回他們的陣列下標。陣列
- python實現給定一個數和陣列,求陣列中兩數之和為給定的數Python陣列
- 如何查詢總和等於給定數字的整數陣列中的所有對陣列
- 給出一個由[-100,100]之間整陣列成的陣列,求其相加和最大的連續子陣列 輸入 一個連續整陣列成的陣列 輸出 子陣列相加的最大值 樣例輸入 -......陣列
- 給定陣列中找到最大的兩個數陣列
- 最大連續子陣列和(最大子段和)陣列
- 寫一個函式找出給定陣列中的最大差值函式陣列
- 2022-06-23:給定一個非負陣列,任意選擇數字,使累加和最大且為7的倍數,返回最大累加和陣列
- 返回陣列中的最大元素個數陣列
- 給定兩個大小為 m 和 n 的正序(從小到大)陣列 nums1 和 nums2。請你找出並返回這兩個正序陣列的中位數。陣列
- 最大連續子陣列和的實現陣列
- 數字陣列最值,總和,平均,中位數 未完待續陣列
- 【簡單演算法】1.兩數之和,給定整數陣列和目標值,找出陣列中2數之和等於目標值的元素演算法陣列
- 寫一個方法找出指定一維陣列所有不重複的元素和個數陣列
- 在一個給定的陣列中查詢陣列中的最大元素是否至少是陣列中每個其他數字的兩倍, 如果是,則返回最大元素的索引,否則返回-1。陣列索引
- js找出陣列中出現最多的元素和次數JS陣列
- lc3041 修改陣列後最大化陣列中的連續元素數目陣列
- 【陣列】1550. 存在連續三個奇數的陣列(簡單)陣列
- 修改陣列【並查集維護集合的最大值、連續數字的最大值】陣列並查集
- 從陣列中找出N個數,其和為M的所有可能陣列
- 連續子陣列的最大和陣列
- 輸入一個整數陣列,輸出奇偶數相間排列的陣列陣列
- 給定一個整數陣列和一個目標值,找出陣列中和為目標值的兩個數。 你可以假設每個輸入只對應一種答案,且同樣的元素不能被重複利用陣列
- 給定一個按非遞減順序排序的整數陣列 A,返回每個數字的平方組成的新陣列,要求也按非遞減順序排序。排序陣列
- 改進,從一個陣列中找出 N 個數,其和為 M 的所有可能陣列
- 【LeetCode】【分治法】連續數列(最大子序和)思路解析和程式碼LeetCode
- 如何從整數陣列中找到最大和最小數陣列
- 《劍指Offer》- 連續子陣列的最大和或最小和陣列
- 最大連續子陣列和求解問題(C語言)陣列C語言
- 給定一個排序陣列和一個目標值,在陣列中找到目標值,並返回其索引。如果目標值不存在於陣列中,返回它將會被按順序插入的位置。排序陣列索引
- 【陣列】1394. 找出陣列中的幸運數(簡單)陣列
- 每日一練(22):連續子陣列的最大和陣列
- 每日一題(一):找出兩個陣列中共有的數字每日一題陣列
- 軟工4/10號作業-C語言最大連續子陣列和問題工作總結軟工C語言陣列
- 陣列[簡單]1550. 存在連續三個奇數的陣列2020/11/14(6)陣列
- 陣列總結,持續更新~陣列
- 求二維陣列中最大子陣列的和陣列
- 給定一個大小為 n 的陣列,找到其中的眾數。眾數是指在陣列中出現次數大於 ⌊ n/2 ⌋ 的元素。陣列