分割数组的最大值最小化(200分 / 二分答案 + 贪心)

题目描述 :给定一个非负整数数组 nums 和一个整数 m,将数组分成 m 个连续子数组,使得这 m 个子数组各自和的最大值最小。输出这个最小值。

输入:

  • 第一行:n m(1 ≤ n ≤ 10^5,1 ≤ m ≤ n)

  • 第二行:n 个非负整数

输出:最小的最大子数组和。

示例:

text

复制代码
输入:
5 2
7 2 5 10 8

输出:
18

解释:分成 [7,2,5] 和 [10,8],最大和为 18。

解题思路

二分答案:

  • 下界 lo = max(nums),上界 hi = sum(nums)。

  • 对于候选值 mid,贪心判断能否用不超过 m 个子数组使每个子数组和 ≤ mid。

  • 若能,说明答案可以更小,hi = mid;否则 lo = mid + 1。

参考代码

c

复制代码
#include <stdio.h>

int canSplit(int *nums, int n, int m, long long limit) {
    int cnt = 1;
    long long sum = 0;
    for (int i = 0; i < n; i++) {
        if (sum + nums[i] > limit) {
            cnt++;
            sum = nums[i];
            if (cnt > m) return 0;
        } else {
            sum += nums[i];
        }
    }
    return 1;
}

int main(void) {
    int n, m;
    scanf("%d %d", &n, &m);

    int nums[100005];
    long long lo = 0, hi = 0;
    for (int i = 0; i < n; i++) {
        scanf("%d", &nums[i]);
        if (nums[i] > lo) lo = nums[i];
        hi += nums[i];
    }

    while (lo < hi) {
        long long mid = lo + (hi - lo) / 2;
        if (canSplit(nums, n, m, mid))
            hi = mid;
        else
            lo = mid + 1;
    }

    printf("%lld\n", lo);
    return 0;
}
相关推荐
CQU_JIAKE1 小时前
10.7【A】
算法
Dfreedom.1 小时前
分类算法的统一视角:从方差最大化到概率建模再到损失函数
算法·支持向量机·分类
Nebula_g2 小时前
JavaSE加强:Commons-io框架
java·开发语言·算法·javase
梦帮科技2 小时前
【3.0修订版】音乐权利 NFT:MusicRightsNFT 的确权思想与授权关联
网络协议·算法·web3·区块链·密码学·智能合约·零知识证明
Dfreedom.2 小时前
基于PCA的光谱物质识别分析
算法
强化湿件的技术神甫3 小时前
KS检验和Lilliefors正态性检验方法
算法
yi0113 小时前
DAY23: LeetCode 27 → 283:从移除元素到移动零,理解快慢指针的两种思路
人工智能·笔记·python·算法·leetcode·排序算法·双指针
怕浪猫3 小时前
多 Agent 系统面试怎么答?我总结了 4 种经典架构
人工智能·算法·面试
程序员清风3 小时前
排序算法:从冒泡排序到归并排序
数据结构·算法·排序算法