問題描述:
給定乙個整數陣列 nums ,找到乙個具有最大和的連續子陣列(子陣列最少包含乙個元素),返回其最大和。
我的思路:
列舉陣列中所有的連續子陣列,找出所有連續子陣列和的最大值。
缺點:
時間複雜度較高o(n^2);
class
solution}}
return max;
}}
動態規劃:
f(i)的求法:
考慮nums[i]應加入f(i-1)對應的那一段還是單獨成一段。這取決於nums[i]+f(i-1)和num[i]的大小,二者取其大。
狀態轉移方程:
f(i) = max;
優點:
相比於暴力列舉,時間複雜度由o(n^2)降為o(n),空間複雜度為o(1).
class
solution
return result;
}}
接下來便是本文的重點初識線段樹分治法(線段樹):整體思路:定義操作:getinfo(nums,0,nums.length - 1);如何實現分治呢?我們取mid = (left+right)>>1;對[left,mid]和[mid+1,right]分治。當區間長度縮為1時開始遞迴回公升。
需要維護的資訊:
*lsum表示[l,r]內以l為左端點的最大子段和
*rsum表示[l,r]內以r為右端點的最大子段和
*msum表示[l,r]內的最大子段和
*isum表示[l,r]的區間和
遞迴回公升時資訊合併:
*isum:左子區間的isum和右子區間的isum之和
*lsum:要麼等於左子區間的lsum,或者左子區間的isum加上右子區間的 lsum,二者取大。
*rsum:要麼等於右子區間的rsum,或者右子區間的isum加上左子區間的 rsum,二者取大。
*msum:左子區間的msum,右子區間的msum,左子區間的rsum加上右子區間的lsum,三者取大。(考慮最大子段是否跨越m)
class
solution
}public
intmaxsubarray
(int
nums)
public status getinfo
(int
nums,
int left,
int right)
public status pushup
(status lsub,status rsub)
}
優點:可以用於解決任意的子區間,而不僅限於[0,nums.length - 1], 如果把分治下去出現的所有子區間的資訊都用堆式儲存的方式記憶化下來,即建成一顆真正的樹之後,我們就可以在o(logn)的時間內求到任意區間內的答案,我們甚至可以修改序列中的值,做一些簡單的維護,之後仍然可以在o(logn)的時間內求到任意區間內的答案,對於大規模查詢的情況下,這種方法的優勢便體現了出來。這棵樹就是上文提及的一種神奇的資料結構——線段樹。
時間複雜度:o(n)
空間複雜度:遞迴使用o(logn)
初識線段樹(線段樹總結)
線段樹的最基本的操作 1 建樹 void construct int left,int right 上述 利用二分的方法,建立一棵葉子節點為 i,i 1 的線段樹 特點是每棵樹的根,一定包含於子樹的線段。2 插入一段線段 void insert int index,int c,int d 解釋 當要...
筆記 線段樹
線段樹和樹狀陣列的功能類似 但是比樹狀陣列強大的是 線段樹可以進行區間的更新操作 不只是單點更新 如把陣列1 3加5 或者把陣列5 6全部改為4 等等 但是線段樹的 量比樹狀陣列要大 記住線段樹的記憶體是普通的四倍!下面 線段樹輸入乙個陣列 改變區間l到r 使a陣列l到r每個加上d 求區間ll到rr...
筆記 線段樹
一顆二叉樹,即為t a,b 引數a,b表示該節點表示區間 a,b 區間長度b a記為l。遞迴定義t a,b 若區間長度l 1 區間 a a b2 a,a b 2 為t的左兒子,區間 a b2 1,b a b2 1,b 為t的右兒子。若區間長度l 1 t為乙個葉子結點,表示區間 a 葉結點為區間內的所...