• 410. 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:
    If n is the length of array, assume the following constraints are satisfied:

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

    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.

    解题思路:

    刚看到这道题没有一点思路,于是参考了HaoxiangXu的解法

    它的解法讲得非常清晰透彻了。

    这里用到了二分法和贪婪算法来一起做。

    首先将问题分成了两个子问题:

    1.  给出一个数组arr,给定分割数m以及每个组的最大和MAX,能否用最多m个分割将数组分成子数组和不超过MAX的子数组?

    2. 给出一个下界left,和一个上界right,一个未知的bool数组(B)以及一个使用i作为输入并且告诉你B[i]是否为true的API。若我们知道,一定存在一个下标k,使得i<k 时,B[i] 为false, i >= k时, B[i]为true。 找到k的最快的方式是什么?

    对于第一个问题, 我们可以使用贪婪算法来解答。在组中加入当前数字n,判断当前的组合是否超出MAX,若超出,则将当前数字作为新的组的起点,更新新的组和为当前数字n,并且分割数减一(因为开始了新的组,我们需要用一个分割来分割两个组)。

    注意此时要判断分割数是否小于0,若分割数小于0,则代表当前分割数无法分割出组和不超过MAX的子数组们。

    对于第二个问题,我们很容易想到二分搜索。

    回归到当前问题,我们需要寻找上界(right)和下界(left)。

    最小的分割为只有一个元素,最大的分割为原数组,所以left = max(arr), right = sum(arr);

    给大神跪了ORZ

    代码:

    class Solution {
    public:
        int splitArray(vector<int>& nums, int m) {
            long long left = 0, right = 0;
            for(int n : nums){
                left = max(left, (long long)n);
                right += (long long)n;
            }
            while(left < right){
                long long mid = left + (right - left)/2;
                if(isWork(nums, m-1, mid)) right = mid;
                else left = mid+1;
            }
            return left;
        }
    private:
        bool isWork(vector<int>& nums, int cuts, long long max){
            int acc = 0;
            for(int n : nums){
                if(n > max) return false;
                if(acc + n <= max) acc += n;
                else{
                    acc = n;
                    cuts--;
                    if(cuts < 0) return false;
                }
            }
            return true;
        }
    };
  • 相关阅读:
    【原】Windows下常用命令
    【转】Samba配置文件详解
    JS笔记-选项卡的重用
    canvas.toDataURL()跨域问题
    Adobe Air 写文件如何换行
    AS3多线程快速入门(三):NAPE物理引擎+Starling[译]
    AS3多线程快速入门(二):图像处理[译]
    AS3多线程快速入门(一):Hello World[译]
    使用FileStream对象读写文件(转)
    Adobe Air写配置文件
  • 原文地址:https://www.cnblogs.com/yaoyudadudu/p/9315822.html
Copyright © 2020-2023  润新知