LeetCode 410. 分割数组的最大值

题目描述:

给定一个非负整数数组和一个整数 m,你需要将这个数组分成 个非空的连续子数组。设计一个算法使得这 个子数组各自和的最大值最小。

注意:
数组长度 满足以下条件:

  • 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,在所有情况中最小。


错误思路:

最开始直接想到的方法是分组:   数1|数2|数3|数4 数5 数6 数7...........  分割线为分组情况, 然后记录下分割线的位置,从最右边的分割线开始,依次将分割线向右边移动,每次判断子数组和的最大值,如果减小就移动下一条分割线,于是很快写出了这样的代码。

JavaScript:

/**
 * @param {number[]} nums
 * @param {number} m
 * @return {number}
 */
var splitArray = function(nums, m) {
        var splitArr=[];
        var valueArr=[];
        var len=nums.length;
        var max=0;
        for(var i=0;i<m;i++)
        {
            splitArr.push(i);
            if(i!=m-1)
                valueArr.push(nums[i]);
        }
        var temp=0;
        for(var i=m-1;i<len;i++)
        {
            temp+=nums[i];
        }
        splitArr.push(len-1);
        valueArr.push(temp);
        max=Math.max.apply(null,valueArr);

        for(var i=m-1;i>0;i--)
        {
            var st=splitArr[i];
            var ed=splitArr[i+1];
            for(var j=st;j<ed;j++)
            {
                var tempA=valueArr.concat();
                tempA[i]-=nums[j];
                tempA[i-1]+=nums[j];
                var tempMax=Math.max.apply(null,tempA);
                if(tempMax<max)
                {
                    max = tempMax;
                    splitArr[i]=j+1;
                    valueArr[i]-=nums[j];
                    valueArr[i-1]+=nums[j];
                }
                else
                {
                    break;
                }
            }
        }
        return max;
};

但是运行的时候不能通过全部的测试用例,分析了一下逻辑,发现陷入了局部最优解。


正确思路:

采用动态规划。用一个二维数组记录情况,记录分组里面子数组各自和的最大值最小的值。dp[i][j]表示将输入数组的前j个数分为i 组。其中有dp[0][0]=0。dp[i-1][k]表示将k个数分为i-1组,j-k个数单独分为一组。那么刚好合起来就是i组。 转变为找所有分组里面子数组和的最大值。在这些最大值里面找到最小的值。

JavaScript:

/**
 * @param {number[]} nums
 * @param {number} m
 * @return {number}
 */
var splitArray = function(nums, m) {
     //动态规划
    var len=nums.length;
    var dp=[];
    var maxArr=[0];
    nums.forEach(function(item,index){
        maxArr[index+1]=maxArr[index]+item;
    });
    for(var i=0;i<=m;i++)
    {
        dp[i]=[];
        for(var j=0;j<=len;j++)
        {
            dp[i][j]=maxArr[maxArr.length-1];
        }
    }

    dp[0][0]=0;
    for(var i=1;i<=m;i++)
    {
        for(var j=1;j<=len;j++)
        {
            for(var k=i-1;k<j;k++)
            {
                var value=Math.max(dp[i-1][k],maxArr[j]-maxArr[k]);
                dp[i][j]=Math.min(dp[i][j],value);
            }
        }
    }

    return dp[m][len];

};

猜你喜欢

转载自blog.csdn.net/cc_fys/article/details/80614373
今日推荐