Split Array Largest Sum

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.

分析:暴力解法

虽然要把数组分成几份,但是因为数组里的元素是连续的,所以,我们可以把前面部分当成第一份,然后找出后边部分分出 m - 1次时最大的和。所以递归方法可解。但是,很明显,cost太高了。
 1 public class Solution {
 2     //brute-force approach
 3     public int splitArray(int[] nums, int m) {
 4         long[] sums = new long[nums.length];
 5         sums[0] = nums[0];
 6 
 7         for (int i = 1; i < sums.length; i++) {
 8             sums[i] = sums[i - 1] + nums[i];
 9         }
10 
11         return (int) helper(nums, sums, 0, sums.length - 1, m);
12     }
13 
14     public long helper(int[] nums, long[] sums, int start, int end, int k) {
15         if (k <= 0)
16             return Integer.MAX_VALUE;
17         if (k == 1) {
18             if (start == 0) {
19                 return sums[end];
20             } else {
21                 return sums[end] - sums[start - 1];
22             }
23         }
24         long min = Long.MAX_VALUE;
25 
26         for (int i = start; i <= end; i++) {
27 
28             long leftSum;
29             if (start == 0) {
30                 leftSum = sums[i];
31             } else {
32                 leftSum = sums[i] - sums[start - 1];
33             }
34 
35             min = Math.min(min, Math.max(leftSum, helper(nums, sums, i + 1, end, k - 1)));
36         }
37         return min;
38     }
39 }

 

第二种方法:

首先找出数组的最大值max和所有值的和sum。然后那个最小值一定是在max和sum之间。 所以可以利用binary search来寻找。

reference: https://discuss.leetcode.com/topic/61315/java-easy-binary-search-solution-8ms

 1 public class Solution {
 2     public int splitArray(int[] nums, int m) {
 3         long sum = 0;
 4         int max = 0;
 5         for (int num : nums) {
 6             max = Math.max(max, num);
 7             sum += num;
 8         }
 9         return (int) binary(nums, m, sum, max);
10     }
11 
12     private long binary(int[] nums, int m, long high, long low) {
13         long mid = 0;
14         while (low <= high) {
15             mid = (high + low) / 2;
16             if (valid(nums, m, mid)) {
17                 high = mid - 1;
18             } else {
19                 low = mid + 1;
20             }
21         }
22         return low;
23     }
24 
25     private boolean valid(int[] nums, int m, long max) {
26         int cur = 0, count = 1;
27         for (int num : nums) {
28             cur += num;
29             if (cur > max) {
30                 cur = num;
31                 count++;
32                 if (count > m) {
33                     return false;
34                 }
35             }
36         }
37         return true;
38     }
39 }
 

转载于:https://www.cnblogs.com/beiyeqingteng/p/6073579.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值