LeetCode410.分割数组的最大值

题目链接🔗: leetcode.cn/problems/sp...

题目描述:

思路+代码:

ini 复制代码
#include<iostream>
#include<vector>
#include<algorithm>

//	最大值最小化问题,同样二分答案,要最小化的最大值有上下界,
//	上界是 sum,下界是 nums 中的最大值,二分尝试这个范围里的每个
//	可能的答案,每一轮通过贪心计算要以当前的估计值作为划分后子数组
//	最大值的话,最少要划分成多少组才能满足,然后用这个计算结果和
//	真实的k作比较。首先要明白这里为什么贪心(这里也就是顺序遍历处理)能
//	实现局部最优到全局最优,首先子数组是连续的,其次第一组贪心策略放入的元素
//	数目一定不会少于其他策略放入的元素数目,后面的分组当然也是同样的道理,
//	换句话说,要在指定最大值限制下分成最少的组数,那我每组的元素当然有尽可能多放,不然留到
//	后面,肯定要占另外的组,也就有可能会造成要划分出新的组,增加了组数。
//	然后再看怎么二分,如果算出来的最小需要划分成的组数小于 k,那也就是
//	说要划分成更多的组,此时我们可以往更小估值,这样可能会有和值比较大的子数组
//	拆开,以使得组数增加; 如果算出来的最小需要划分成的组数等于 k,那就继续往小估,
//	因为有可能有更小的最大值也能满足最小需要组数等于 k, 注意这里只是可能,所以
//	r 不能移到 mid - 1, 而是移到 mid; 如果算出来的最小需要划分成的组数大于 k,
//	便要通过增大估值,这样可能会有和值比较小的子数组被合并,以使得组数减少。
//	
//	这里也做了小的优化,就是当当前估的最大值不是任何贪心划分出来的子数组和的时候, 
//	我们在贪心的时候获取实际子数组中和的最大值,然后在 min_k<=k 同时 max_sum < m 的
//	时候直接 r = max_sum。 
//	
//	复杂度:O(nlog(sum)) 


std::vector<int> get_min_k(std::vector<int>&nums, int m){
        int t = nums.size();
        int count = 0, tem_sum = 0, max_sum = -1;
        for(int i=0; i<t; i++){
                if(tem_sum+nums[i]>m){
                        count ++;
                        max_sum = std::max(max_sum, tem_sum);
                        tem_sum = nums[i];
                }
                else{
                        tem_sum += nums[i];
                }
        }
        return {count+1, std::max(max_sum, tem_sum)};
}

int splitArray(std::vector<int>& nums, int k) {
    int t = nums.size(), res = 0;
    int sum = 0, max_num = -1;
    for(int i = 0; i<t; i++){
        sum += nums[i];
        max_num = std::max(max_num, nums[i]);
        }
        int l = max_num, r = sum;
        while(l<r){
                int m = (l+r)/2;
                int min_k = get_min_k(nums, m)[0];
                int max_sum = get_min_k(nums, m)[1];
                if(min_k<=k) max_sum < m ? r = max_sum : r = m;
                else l = m + 1;
        }
        return l;
}

int main(){
        int n, a, k;
        std::cin >> n;
        std::vector<int> nums; 
        for(int i=0; i<n; i++){
                std::cin >> a;
                nums.push_back(a); 
        }
        std:: cin >> k;
        std:: cout << splitArray(nums, k);
        return 0;
}
相关推荐
垆边人似月.1 小时前
华为题:字符串中最长连续数字串
开发语言·c++·算法
_不会dp不改名_1 小时前
leetcode_3273 数位平方和的最大值
算法·leetcode·职场和发展
vivo互联网技术1 小时前
SSR-Merge:把 LoRA 合并从"参数算术"变成"信号路由" | ICML 2026
人工智能·算法·计算机视觉
罗湖老棍子1 小时前
座位安排(洛谷-P2071)
c++·算法·图论·匈牙利算法·二分图匹配
巴糖1 小时前
挑礼物这件事,暴露了你做选择时最大的问题
算法
用户7341681035481 小时前
控制与监测特征的联合表征:复杂动力装备变工况故障诊断的发展方向
算法
垆边人似月.1 小时前
华为题:无重复字符的最长子串变种
算法
糖果豆豆1 小时前
灾难性遗忘不是"新旧打架"——旧知识记不住,是因为它没长成"环"
算法
垆边人似月.1 小时前
华为题:任务调度
数据结构·c++·算法