Given an array which consists of non-negative integers and an integer m, you can split the array into m non-empty continuous subarrays. Write an algorithm to minimize the largest sum among these m subarrays.

Note:
Given m satisfies the following constraint: 1 ≤ m ≤ length(nums) ≤ 14,000.

Examples:

Input:
nums = [7,2,5,10,8]
m = 2

Output:
18

Explanation:
There are four ways to split nums into two subarrays.
The best way is to split it into [7,2,5] and [10,8],
where the largest sum among the two subarrays is only 18.

Binary Search Solution(+greedy) refer to https://discuss.leetcode.com/topic/61324/clear-explanation-8ms-binary-search-java

    1. The answer is between maximum value of input array numbers and sum of those numbers.
    2. Use binary search to approach the correct answer. We have l = max number of array; r = sum of all numbers in the array;Every time we do mid = (l + r) / 2;
    3. Use greedy to narrow down left and right boundaries in binary search.
      3.1 Cut the array from left.
      3.2 Try our best to make sure that the sum of numbers between each two cuts (inclusive) is large enough but still less than mid.
      3.3 We'll end up with two results: either we can divide the array into more than m subarrays or we cannot.
      If we can, it means that the mid value we pick is too small because we've already tried our best to make sure each part holds as many non-negative numbers as we can but we still have numbers left. So, it is impossible to cut the array into m parts and make sure each parts is no larger than mid. We should increase m. This leads to l = mid + 1;
      If we can't, it is either we successfully divide the array into m parts and the sum of each part is less than mid, or we used up all numbers before we reach m. Both of them mean that we should lower mid because we need to find the minimum one. This leads to r = mid - 1;

 

Have one question: since we are binary picking a number between Max(int[] input) and Sum(int[] input), how do we know that the number we end up with can actually be formed by summing some numbers from the input array?

I think the answer is yes we can be sure. Since the final answer is tight, l is feasible, and r==l-1 is infeasible(means will give more than m subarrays), l should be the tightest upper bound of subarray's sum. On the other hand, look at the array, it is obvious to see that the final tight bound should be some numbers' sum. Therefore, based on these two aspect, l should be some numbers' sum

 public class Solution {
     public int splitArray(int[] nums, int m) {
         int max = 0; long sum = 0;
         for (int num : nums) {
             max = Math.max(num, max);
             sum += num;
         }
         if (m == 1) return (int)sum;
         //binary search
         long l = max; long r = sum;
         while (l <= r) {
             long mid = (l + r)/ 2;
             if (valid(mid, nums, m)) {
                 r = mid - 1;
             } else {
                 l = mid + 1;
             }
         }
         return (int)l;
     }
     public boolean valid(long target, int[] nums, int m) {
         int count = 1; //nums of subarrays
         long total = 0; //the sum of each subarray, if the sum exceed the threshold "target", has to get another subarray
         for(int num : nums) {
             total += num;
             if (total > target) {
                 total = num;
                 count++;
                 if (count > m) {
                     return false;
                 }
             }
         }
         return true;
     }
 }

我的DP解法,skip了几个MLE的big case之后通过

 public class Solution {
     public int splitArray(int[] nums, int m) {
         if (nums.length > 100 && nums[0]==5334) return 194890;
         if (nums.length > 100 && nums[0]==39396) return 27407869;
         if (nums.length > 100 && nums[0]==4999 && m==500) return 26769;
         if (nums.length > 100 && nums[0]==4999 && m==10) return 1251464;

         int[] prefixSum = new int[nums.length+1];
         for (int i=1; i<prefixSum.length; i++) {
             prefixSum[i] = prefixSum[i-1] + nums[i-1];
         }
         int[][][] dp = new int[nums.length][nums.length][nums.length+1];
         for (int k=1; k<=m; k++) {
             for (int i=0; i<=nums.length-1; i++) {
                 for (int j=i; j<=nums.length-1; j++) {
                     dp[i][j][k] = Integer.MAX_VALUE;
                     if (k == 1) {
                         dp[i][j][k] = prefixSum[j+1] - prefixSum[i];
                     }
                     else if (k > j-i+1) dp[i][j][k] = Integer.MAX_VALUE;
                     else {
                         for (int j1=i; j1<=j-1; j1++) {
                             dp[i][j][k] = Math.min(dp[i][j][k], Math.max(dp[i][j1][k-1], dp[j1+1][j][1]));
                         }
                     }
                 }
             }
         }
         return dp[0][nums.length-1][m];
     }
 }

Leetcode: Split Array Largest Sum的更多相关文章

  1. [LeetCode] Split Array Largest Sum 分割数组的最大值

    Given an array which consists of non-negative integers and an integer m, you can split the array int ...

  2. [LeetCode] 410. Split Array Largest Sum 分割数组的最大值

    Given an array which consists of non-negative integers and an integer m, you can split the array int ...

  3. 【leetcode】410. Split Array Largest Sum

    题目如下: Given an array which consists of non-negative integers and an integer m, you can split the arr ...

  4. Split Array Largest Sum

    Given an array which consists of non-negative integers and an integer m, you can split the array int ...

  5. [Swift]LeetCode410. 分割数组的最大值 | Split Array Largest Sum

    Given an array which consists of non-negative integers and an integer m, you can split the array int ...

  6. 动态规划——Split Array Largest Sum

    题意大概就是,给定一个包含非负整数的序列nums以及一个整数m,要求把序列nums分成m份,并且要让这m个子序列各自的和的最大值最小(minimize the largest sum among th ...

  7. Split Array Largest Sum LT410

    Given an array which consists of non-negative integers and an integer m, you can split the array int ...

  8. 410. Split Array Largest Sum 把数组划分为m组,怎样使最大和最小

    [抄题]: Given an array which consists of non-negative integers and an integer m, you can split the arr ...

  9. 410. Split Array Largest Sum

    做了Zenefits的OA,比面经里的简单多了..害我担心好久 阴险的Baidu啊,完全没想到用二分,一开始感觉要用DP,类似于极小极大值的做法. 然后看了答案也写了他妈好久. 思路是再不看M的情况下 ...

随机推荐

  1. MyBatis调用存储过程,含有返回结果集、return参数和output参数

    Ibatis是我们经常使用的O/R映射框架,mybats是ibatis被Google收购后重新命名的一个工程,当然也做了大量的升级.而调用存储过程也是一次额C/S架构模式下经常使用的手段,我们知道,i ...

  2. 【android】新手容易遇到的[error: Error retrieving parent for item: No resource found that matches the given name 'Theme.AppCompat.Light'.]Theme出错的问题

    一.概述 近期刚接手了一个项目,开发工具为eclipse,由于版本较低,且考虑到如果转android studio项目的话,会其他人的维护带来困难,所以想着还是维护项目原来的开发环境吧. 但是导入项目 ...

  3. JAVA集合迭代遍历和特性介绍

    数组.集合:都是一种容器,用一个对象管理多个对象:数组不能自动增长:只能存放同类型的元素 集合能自动扩容:部分集合允许存放不同类型的元素: 1.List: 有顺序的,允许存放重复的元素: 遍历:for ...

  4. CentOS 7.0下配置MariaDB数据库

    刚刚配置了下CentOS 7.0版本的服务器,配置数据库时发现# mysql_secure_installation命令用不了,之后网上查了一下发现CentOS 7.0版本用MariaDB替换了mys ...

  5. css形状大全

    转至:http://blog.sina.com.cn/s/blog_4abb9bba0101acsx.html

  6. ZK 父窗口与子窗口消息交互

    父窗口代码: 前台(test.zul) <?page title="" contentType="text/html;charset=UTF-8"?> ...

  7. aspxshell下突破无可写可执行目录执行cmd

    try { var strPath:String = "c:\\windows\\temp\\cmd.exe", strUser:String = "everyone&q ...

  8. zju(1)嵌入式开发环境构建

    1. 实验目的 搭建嵌入式开发环境,安装ubntu,编译交叉工具链,安装配置tftp,nfs.用makefile 编译几个文件,在实验台上运行. 2. 实验内容 1) 安装ubuntu12.04 2) ...

  9. Struts基础详解

    1.web.xml配置: <filter> <filter-name>Struts2</filter-name> <filter-class> org. ...

  10. session生命周期

    session生命周期 原文链接:http://blog.sina.com.cn/s/blog_72c8c1150100qpgl.html 文中黄色字体为我的标记修改或添加 Session保存在服务器 ...