欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【刷题】410. 分割数组的最大值

程序员文章站 2022-07-01 17:17:03
...

题目:

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

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

1 ≤ n ≤ 1000
1 ≤ m ≤ min(50, n)

【刷题】410. 分割数组的最大值

 

方法一:二分法

由题意可知:子数组的最大值是有范围的,即在区间 [nums的最大元素值,nums的元素之和]之中。

令 left=nums的最大元素值,right=nums的元素之和,mid=(left+right)/2.计算数组和最大值不大于mid对应的子数组个数 cnt(这个是关键!)

如果 cnt>m,说明划分的子数组多了,即我们找到的 mid 偏小,故 left=mid+1;
否则,说明划分的子数组少了,即 mid 偏大(或者正好就是目标值),故right=mid。

	public int splitArray(int[] nums, int m) {
        int left = 0, right = 0;
        for (int i = 0; i < nums.length; i++) {
            right += nums[i];//求和
            if (left < nums[i]) {
                left = nums[i];//找nums的最大元素
            }
        }
        while (left < right) {
            int mid = (right - left) / 2 + left;
            if (check(nums, mid, m)) {//查看mid是否满足条件,当right=left的时候就跳出循环了
                right = mid;
            } else {
                left = mid + 1;
            }
        }
        return left;
    }

    public boolean check(int[] nums, int x, int m) {
        int sum = 0;
        int cnt = 1;
        for (int i = 0; i < nums.length; i++) {
            if (sum + nums[i] > x) {
                cnt++;
                sum = nums[i];
            } else {
                sum += nums[i];
            }
        }
        return cnt <= m;
    }

 

 

相关标签: 刷题