題目描述:給定一個整數陣列 nums 和整數 k,將陣列劃分為恰好 k 個連續子陣列。每個子陣列的「分數」為其最大值與最小值之差。整體分數為所有子陣列分數的最大值。求最小化整體分數。
解題思路:二分搜尋答案。二分搜尋整體分數的目標值 mid,然後驗證是否能將陣列劃分為至多 k 個子陣列,使得每個子陣列的 max - min <= mid。
驗證函數使用貪心策略:從左到右掃描,盡可能讓每個子陣列越長越好。使用兩個變數追蹤當前子陣列的 max 和 min,當 max - min > mid 時,切斷並開始新的子陣列。若切斷次數 < k,則 mid 可行。
但要注意:當需要恰好 k 段時,貪心的「盡量長」策略可能不是最優的。此時需要用 DP + 單調佇列的方法,或者觀察到:若能分成 <= k 段(每段 max-min <= mid),也一定能恰好分成 k 段。
時間複雜度:O(n log D) — D 為陣列的值域範圍(max - min)。二分搜尋 O(log D) 層,每層貪心驗證 O(n)。
空間複雜度:O(1) — 只需常數額外空間。
1. Binary search on answer `mid` (range: 0 to max(nums) - min(nums)) 2. For each `mid`, validate with greedy: a. Scan left to right, track current subarray's max and min b. When max - min > mid: start new subarray, increment parts count c. If parts <= k: feasible 3. Return minimum feasible `mid`
DP + 單調佇列 O(n * k):令 dp[i][j] = 前 i 個元素分成 j 段的最小最大分數。轉移需要枚舉最後一段的起點,用單調佇列優化到 O(1) 攤銷轉移。適合 k 較小的情況。
分治法:將陣列分為兩半,分別求解後合併。但合併步驟需要考慮跨越中點的劃分,較為複雜。