前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >LeetCode 410. 分割数组的最大值(极小极大化 二分查找 / DP)

LeetCode 410. 分割数组的最大值(极小极大化 二分查找 / DP)

作者头像
Michael阿明
发布2021-02-19 10:21:40
6570
发布2021-02-19 10:21:40
举报
文章被收录于专栏:Michael阿明学习之路

文章目录

1. 题目

给定一个非负整数数组和一个整数 m,你需要将这个数组分成 m 个非空的连续子数组。

设计一个算法使得这 m 个子数组各自和最大值最小

代码语言:javascript
复制
注意:
数组长度 n 满足以下条件:
1 ≤ n ≤ 1000
1 ≤ m ≤ min(50, n)

示例:
输入:
nums = [7,2,5,10,8]
m = 2

输出:
18
解释:
一共有四种方法将nums分割为2个子数组。
其中最好的方式是将其分为[7,2,5] 和 [10,8],
因为此时这两个子数组各自的和的最大值为18,在所有情况中最小。

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/split-array-largest-sum 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2. 解题

2.1 二分查找

类似题目:

LeetCode 875. 爱吃香蕉的珂珂(二分查找)

LeetCode LCP 12. 小张刷题计划(二分查找)

LeetCode 1011. 在 D 天内送达包裹的能力(二分查找)

LeetCode 1062. 最长重复子串(二分查找)

LeetCode 5438. 制作 m 束花所需的最少天数(二分查找)

LeetCode 1102. 得分最高的路径(优先队列BFS/极大极小化 二分查找)

LeetCode 1231. 分享巧克力(极小极大化 二分查找)

代码语言:javascript
复制
class Solution {
public:
    int splitArray(vector<int>& nums, int m) {
    	long long l = 0, r = 1e15, maxsum, ans;
    	while(l <= r)
    	{
    		maxsum = l+((r-l)>>1);
    		if(canSplitM(nums, maxsum, m))
    			r = maxsum-1, ans = maxsum;
    		else
    			l = maxsum+1;
    	}
    	return ans;
    }
    bool canSplitM(vector<int>& nums, long long maxsum, int m) 
    {
    	int count = 0;
    	long long sum = 0;
    	for(int i = 0; i < nums.size(); ++i)
    	{
    		if(sum+nums[i] <= maxsum)//和的最大值没有超过设定的maxsum
    			sum += nums[i];
    		else//超过了
    		{
    			count++;
    			sum = 0;
    			i--;
    		}
    		if(count >= m)
    			return false;
    	}
    	return true;
    }
};

0 ms 7 MB

2.2 DP

  • dpi 表示前 i 个数,分成 j 组的最小的最大和的值
  • 先预处理求出前缀和 sum

代码语言:javascript
复制
class Solution {
public:
    int splitArray(vector<int>& nums, int m) {
        int n = nums.size(), i, j, k;
        vector<long long> sum(n+1, 0);
        for(i = 1; i <= n; ++i)
            sum[i] = sum[i-1] + nums[i-1];
        vector<vector<long long>> dp(n+1, vector<long long>(m+1,1e15));
        dp[0][0] = 0;
        for(i = 1; i <= n; ++i)
            for(j = 1; j <= min(i,m); ++j)
                for(k = 0; k <= i; ++k)
                    dp[i][j] = min(dp[i][j], max(dp[k][j-1], sum[i]-sum[k]));
        return dp[n][m];
    }
};

412 ms 8.2 MB

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/07/25 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 1. 题目
  • 2. 解题
    • 2.1 二分查找
      • 2.2 DP
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档