[Leetcode][第410题][JAVA][分割数组的最大值][动态规划][二分]
【問題描述】[中等]
【解答思路】
1. 動態規劃
第 1 步:設計狀態
令 f[i][j] 表示將數組的前 i 個數分割為 j 段所能得到的最大連續子數組和的最小值。 ( i ≥ j )
第 2 步:狀態轉移方程
第 3 步:考慮初始化
f[i][j] = Integer.MAX_VALUE
f[0][0]=0
第 4 步:考慮輸出
f[n][m]f[n][m]
復雜度
2. 二分+貪心
nums = [7,2,5,10,8]
m = 1,那么整個數組作為一部分,最小的最大值為 32
m = n,那么每個元素作為一個子數組,從所有元素選取最大值,最小的最大值小為 10
m 的取值范圍為 1 <= m <= n,因此,最大值的最小值的范圍為 [10, 32]
我們利用二分法查找,找出符合 m 的最大值的最小的結果
二分過程:
left = 10;
right = 32
mid = (left + right) >>> 1 = 21(這個 21 就是一個子數組的最大容量)
我們假設剛開辟的用來存儲的子數組個數 cnt = 1
那么根據貪心思想,我們將數組元素按順序逐個往里放
因此就有如下過程:
7 < 21
7 + 2 < 21
7 + 2 + 5 < 21
7 + 2 + 5 + 10 > 21
至此,我們可以看出一個 21 容量的子數組是無法容納整個數組元素的,因此我們需要開辟第二個子數組來存儲剩下的數組元素
cnt = cnt + 1 = 2
10 < 21
10 + 8 < 21
我們發現,兩個子數組可以將整個數組元素放入,而 cnt 剛好等于 m,因此 [7,2,5] 和 [10,8] 就是分割出來的兩個子數組,最小的最大值為 18
區間縮小 (建議在草稿紙上模擬過程)
為什么是放入元素直到放不下為止?因為要求的是連續子數組,我們需要保證每個連續的子數組的元素和都盡可能的接近 21
如果我們最終得到的 cnt > m,那么表示我們劃分出太多的子數組,也就是意味著一個子數組的容量太少,我們需要再擴大容量,即 left = mid + 1,然后繼續進行二分
如果我們最終得到的 cnt < m,那么表示我們劃分出太少的子數組,也就是意味著一個子數組的容量太大,需要減少容量,即 right = mid
復雜度
【總結】
1. 動態規劃流程
第 1 步:設計狀態
第 2 步:狀態轉移方程
第 3 步:考慮初始化
第 4 步:考慮輸出
第 5 步:考慮是否可以狀態壓縮
2.細節
Arrays.fill()并不能提高賦值的效率,在函數的內部也是用for循環的方式 實現的。
fill()函數源碼:
等價于
for (int i = 0; i <= n; i++) {for(int j =0 ;j<=m;j++){f[i][j] = Integer.MAX_VALUE;}}3.審題認真! Java函數不懂可以看源碼, 效率超高!(總比瞎猜好)
參考鏈接:https://leetcode-cn.com/problems/split-array-largest-sum/solution/er-fen-cha-zhao-by-liweiwei1419-4/
參考鏈接:https://leetcode-cn.com/problems/split-array-largest-sum/solution/fen-ge-shu-zu-de-zui-da-zhi-by-leetcode-solution/
總結
以上是生活随笔為你收集整理的[Leetcode][第410题][JAVA][分割数组的最大值][动态规划][二分]的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我的atom插件
- 下一篇: [Leetcode][第459题][JA