LeetCode410. 分割数组的最大值

LeetCode410. 分割数组的最大值

给定一个非负整数数组和一个整数 m,你需要将这个数组分成 m 个非空的连续子数组。设计一个算法使得这 m 个子数组各自和的最大值最小。
注意: 数组长度 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,在所有情况中最小。

解析:
  • 解法一:动态规划

    动态规划的思路很简单,但算法复杂度较高

    当一个数组nums,已知其前j个数,分k-1组的子数组最大和为dp[j][k-1]

    前i个数分为k组的子数组最大和dp[i][k]=Math.max( d p [ j ] [ k − 1 ] dp[j][k-1] dp[j][k1], ∑ n = k − 2 i − 1 n u m s [ n ] \sum^{i-1}_{n=k-2}nums[n] n=k2i1nums[n]),

    具体代码如下:

class Solution {

    public int splitArray(int[] nums, int m) {
        if(m==0){
            return 0;
        }
        int[][] dp = new int[nums.length][nums.length];
        for(int i=0;i

解法二: 二分法

分析:

  1. 首先,对于这个问题,数组nums如果按照一个数分一组,那么最大和即为max(nums),如果所有数在同一组,那么最大和为sum(nums),而这两个值也就是所有可能解的上下界;
  2. 接着,选取一种中间值,按照这个中间值分组,使得每组和小于mid,且放入的元素最多,记录总分组数;
  3. 最后如果分组数大于给定的分组数,那么说明每组装少了,需要增大下界;如果分组数小于等于给定的分组数,那么说明每组还能装更多的数,也就是减小上界。

具体逻辑见代码注释:

public int splitArray(int[] nums, int m) {
     
        //二分法是一种基于假设最大值并搜索的方法找到的
        //max和min是最后结果所有可能值的上下限,如果可以一个数一组,那么结果是min,
    	//如果所有数一组,结果为max
        long min=0,max=0;
        //初始化min,max
        for(int i:nums){
     
            max+=i;
            if(i>min){
     
                min=i;
            }
        }
        long res = max;
        //开始搜索
        while(min<max){
     
            //这一轮循环认为每一组最大和为(min+max)/2
            long mid = (min+max)>>1;
            //sum存储每一组的和
            long sum=0;
            int group=1;
            for(int i: nums){
     
                //分组和超过了mid,则重新分一组
                if(sum+i>mid){
     
                    sum=i;
                    group++;
                }else{
     
                    sum+=i;
                }
            }
            //如果分组多了,那说明我们每组和小了,提高我们分组和范围的下界,
            //则可以让更多的数进入同一组
            if(group>m){
     
                min=mid+1;
            }else{
     
                //如果分组少了,那说明我们每组和大了,降低我们分组和范围的上界,
                //则可以让更少的数进入同一组
                res=Math.min(res,mid);
                max=mid-1;
            }
        }
        return (int)res;
    }

你可能感兴趣的:(算法与数据结构,二分法,算法,leetcode,动态规划,java)