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. HDU 4741 Save Labman No.004(计算几何)

    题目链接 抄的模版...mark一下. #include <iostream> #include <cstring> #include <cstdio> #incl ...

  2. 升级到EF6 两个注意事项

    1.依据MSDN的官方描述: In previous versions of EF the code was split between core libraries (primarily Syste ...

  3. BZOJ3992: [SDOI2015]序列统计

    Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S. 小C用这个生成器生成了许多这样的数列. ...

  4. 深入浅出 - Android系统移植与平台开发(十一) - Sensor HAL框架分析之一

    作者:唐老师,华清远见嵌入式学院讲师. 1. Sensor的概念 Sensor即传感器,在当前智能手机上大量存在:G-Sensor.LightsSensor. ProximitySensor.Temp ...

  5. Hightcharts设置Y轴最大最小值

    有两种方法: 1:是在控件初始化时预设, yAxis: [{ max:}] 2:在程序运行中动态更新设置 thChart.yAxis[].update({ min: , max: });

  6. Java语言基础

    Java 语言是面向对象的程序设计语言,Java 程序的基本组成单元是类,类体中又包括属性与方法两部分.每一个应用程序都必须包含一个main()方法,含有main()方法的类成为主类. 一.Java ...

  7. QSpinBox 和 QSlider 联合使用方法

    在Qt中,有时候我们想要联合QSpinBox 和 QSlider,使得移动滑块,QSpinBox中的数据会变化,或者我们在QSpinBox中输入一个数值,响应的滑块也会变化,如下图所示:

  8. 您的服务器没有安装这个PHP扩展:OpenSSL(其他平台API同步需要)

    今天在安装一个博客系统的时候提示这个错,在网上找了半天,自己慢慢弄出来的,具体如下: 1.找到你的php.ini 文件,将“;extension=php_openssl.dll”前面分号去掉. 2.复 ...

  9. 类似input框内最右边添加图标,有清空功能

    <html> <head> <meta http-equiv="Content-Type" content="text/html; char ...

  10. 关于WPF中ItemsControl系列控件中Item不能继承父级的DataContext的解决办法

    WPF中所有的集合类控件,子项都不能继承父级的DataContext,需要手动将绑定的数据源指向到父级控件才可以. <DataGridTemplateColumn Header="操作 ...