410 分割陣列的最大值(二分查詢 動態規劃)

2021-10-10 02:36:33 字數 2065 閱讀 5224

1. 問題描述:

給定乙個非負整數陣列和乙個整數 m,你需要將這個陣列分成 m 個非空的連續子陣列。設計乙個演算法使得這 m 個子陣列各自和的最大值最小。

注意:陣列長度 n 滿足以下條件:

示例:

輸入:nums = [7,2,5,10,8]

m = 2

輸出:18

2. 思路分析:

① 分析題目可以知道我們需要將陣列分為m個連續的子陣列,並且使得這些子陣列的各自和的最大值最小,所以我們一開始要確定乙個最大和,然後在這個最大和的情況下判斷出nums陣列是否可以劃分為m個連續的子陣列,這裡比較難想到的一點是可以使用二分查詢的方法去解決,我們在一開始的時候先確定乙個最小與最大範圍,最下範圍比較好確定,主要還是最大範圍的確定,這裡可以採用乙個比較大的數字嘗試一下提交上去是否可以通過,所以最小範圍與最大範圍基本上可以確定,我們只需要在這個範圍內二分查詢然後嘗試最大和為中間值是否可以劃分為m個子陣列,判斷是否可以劃分為m個子陣列比較簡單一點的想法是迴圈遍歷nums陣列,累加當前遍歷的nums[i],當發現累加的和超過了中間值mid之後那麼分組的計數加1,當發現分組的數目等於了m之後那麼肯定是不滿足條件的因為是在超出了mid值的時候才累加分組的數目的,在剩下的元素中至少還存在一組的分組所以最終的分組數目至少是m + 1,並且還有一種情況是當前遍歷的元素值本身大於了mid,這兩種情況都是不能夠劃分為m個分組的,直接返回false即可,否則返回true

② 對於這種題目感覺需要多做一些類似的題目才可以很好地反映出來

③ 第二種思路是動態規劃:感覺動態規劃dp陣列的含義比較好像一點但是狀態轉移方程需要多動點腦筋才可以想出來(dp陣列最難的就是具體的含義以及怎麼樣根據子狀態轉移到現在的狀態)

3. **如下:

from typing import list

class solution:

# 檢查是否可以劃分為m個陣列: 使用貪心的策略盡可能使得當前分組接近於m

def check(self, nums: list[int], m: int, maxsum: int):

count, sum = 0, 0

for i in range(len(nums)):

if sum + nums[i] <= maxsum:

sum += nums[i]

else:

count += 1

sum = nums[i]

if count == m or nums[i] > maxsum: return false

return true

def splitarray(self, nums: list[int], m: int) -> int:

l, r = 0, 10 ** 10

res = 0

while l <= r:

mid = (l + r) // 2

if self.check(nums, m, mid):

r = mid - 1

res = mid

else:

l = mid + 1

return res

官網的動態規劃**:

class solution:

def splitarray(self, nums: list[int], m: int) -> int:

n = len(nums)

f = [[10**18] * (m + 1) for _ in range(n + 1)]

sub = [0]

for elem in nums:

f[0][0] = 0

for i in range(1, n + 1):

for j in range(1, min(i, m) + 1):

for k in range(i):

f[i][j] = min(f[i][j], max(f[k][j - 1], sub[i] - sub[k]))

return f[n][m]

410 分割陣列的最大值

給定乙個非負整數陣列和乙個整數 m,你需要將這個陣列分成 m 個非空的連續子陣列。設計乙個演算法使得這 m 個子陣列各自和的最大值最小。令dp i j 表示陣列前i個數分成j段時的最小和,那麼我們可以列舉k,表示前k個數分成了j 1段,那麼後k 1到i個數就被分成了一段,此時狀態轉移方程就是 sub...

410 分割陣列的最大值

給定乙個非負整數陣列和乙個整數 m,你需要將這個陣列分成 m 個非空的連續子陣列。設計乙個演算法使得這 m 個子陣列各自和的最大值最小。注意 陣列長度 n 滿足以下條件 示例 輸入 nums 7,2,5,10,8 m 2 輸出 18 解釋 一共有四種方法將nums分割為2個子陣列。其中最好的方式是將...

410 分割陣列的最大值

給定乙個非負整數陣列和乙個整數 m,你需要將這個陣列分成 m 個非空的連續子陣列。設計乙個演算法使得這 m 個子陣列各自和的最大值最小。注意 陣列長度 n 滿足以下條件 1 n 1000 1 m min 50,n 示例 輸入 nums 7,2,5,10,8 m 2 輸出 解釋 一共有四種方法將num...