410. Split Array Largest Sum

https://leetcode.com/problems/split-array-largest-sum/

对由非负数组成的数组划分成给定的m份,最小化和最大的子数组。解这种给定背包数,找能把物品(质量值为正数)一一全部放进去的背包最小容量的题用二分最快。对每个二分mid时检查mid是否能让数组在m次分完,当需要的次数大于D时说明mid取小了,start + 1。

/*
 * @lc app=leetcode id=410 lang=cpp
 *
 * [410] Split Array Largest Sum
 */
class Solution {
public:
    int splitArray(vector<int>& nums, int m) {
        const auto check = [](vector<int>& weights, long mid) {
            long sum = 0, c = 1;
            for (int w : weights) {
                if (sum + w > mid) {
                    sum = 0;
                    ++c;
                } 
                sum += w;
            }
            return c;
        };
        long start = 1, end = 1;
        for (int w : nums) {
            start = max(start, (long) w);
            end += w;
        }
        while (start < end) {
            long mid = start + (end - start) / 2;
            if (m < check(nums, mid)) {
                start = mid + 1;
            } else {
                end = mid;
            }    
        }
        return start;
    }
};

partition + optimal用DP。action为对让当前num[j]分别和不同的前面的元素k组成一个划分[k+1, j],受限于前面的划分数目。因此把划分数encoding进状态,题目所求encoding进值,dp[i][j]表示从0到j形成i个划分的最优解,前面[0, k]有i - 1个划分,即dp[i - 1][k]。三重循环。

代码参考了花花的。

Last updated

Was this helpful?