410. Split Array Largest Sum

本文介绍了一种算法,旨在解决将数组分割成多个连续子数组的问题,目标是最小化这些子数组中最大的和。提供了两种解决方案:一种是使用动态规划,另一种是采用二分搜索法。动态规划确保了正确性,而二分搜索法则更注重效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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.


dp[i][j]表示nums数组从index=0到index=i,切j刀最小的和,dp[i][j]=min(max(dp[i][k],sums[i]-sums[k])),其中j-1<=k<=i-1,

然而二维数组开不下。

public class Solution {
    public static int splitArray(int[] nums, int m)
	{
		int len=nums.length;
		int[] sums=new int[len];
		int sum=0;
		for(int i=0;i<len;i++)
		{
			sum+=nums[i];
			sums[i]=sum;
		}
		
		int[][] dp=new int[len][len];
		for(int i=0;i<len;i++)
			dp[i][0]=sums[i];
				
		for(int i=0;i<len;i++)
			for(int j=1;j<len;j++)
			{
				if(j>i)
					continue;
				int min=Integer.MAX_VALUE;
				for(int k=i-1;k>=j-1;k--)
					min=Math.min(min, Math.max(dp[k][j-1], sums[i]-sums[k]));
				dp[i][j]=min;
			}
		
		return dp[len-1][m-1];
	}
}


----------------------------------------------------------------------

二分搜索法,摘自

https://discuss.leetcode.com/topic/61324/clear-explanation-8ms-binary-search-java/9


  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 thanmid.
    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;
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;
        long total = 0;
        for(int num : nums) {
            total += num;
            if (total > target) {
                total = num;
                count++;
                if (count > m) {
                    return false;
                }
            }
        }
        return true;
    }
}

### 关于 `that.$util.SplitArray` 的使用方法 在 UniApp 开发环境中,通过全局挂载工具函数库可以方便地调用自定义辅助功能。根据提供的代码片段,在 main.js 文件中已经将 utils/util.js 下的功能作为原型属性 $util 挂载到了 Vue 实例上[^1]。 对于 `SplitArray` 方法的具体实现细节并未直接展示出来,但是可以根据常见做法推测其行为模式以及如何正确使用它: #### 假设的 SplitArray 函数签名 ```javascript function SplitArray(array, chunkSize) { let result = []; for (let i = 0; i < array.length; i += chunkSize) { result.push(array.slice(i, i + chunkSize)); } return result; } ``` 此假设性的 `SplitArray` 接受两个参数:一个是待分割的一维数组;另一个是指定每组元素数量大小的整数。该函数会按照指定的数量来切割原始数组并返回一个新的二维数组集合。 #### 使用实例说明 当需要在一个页面或者组件内部调用这个方法时,可以通过如下方式完成操作: ```html <template> <div> <!-- 组件模板 --> </div> </template> <script> export default { data() { return { originalArray: ['a', 'b', 'c', 'd', 'e'], chunkedArrays: [] }; }, methods: { splitAndShow() { // 调用已注册的方法 this.chunkedArrays = this.$util.SplitArray(this.originalArray, 2); console.log('分片后的数组:', this.chunkedArrays); } }, mounted(){ this.splitAndShow(); } }; </script> ``` 上述例子展示了怎样利用 `$util.SplitArray()` 对给定的数据列表进行处理,并将其结果显示出来的过程。需要注意的是实际项目中的 `SplitArray` 可能会有不同的名称或者是更复杂的行为逻辑,具体取决于开发者的设计意图。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值