algorithm final 1

Wed, Sep 1, 2021 3-minute read

Split Array Largest Sum 410

二分求最大最小

Given an array nums 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.

 

Example 1:

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.

暴力解法

[7, 12, 2, 5, 6, 8, 3] m = 3 / / \
7 7,12 7, 12, 2, 5, 6, 8, 3

2 分 最大最小就会用到

[7, 12, 2, 5, 6, 8, 3] m = 3

lo = max(nums) 12, 当 m 很多很多的时候,达到了 n - 1 个

hi = 43 当 m 就一个的时候数值

2 分分的是 m 的值

DO binary search while lo < hi

  • iteration
  • mid
  • is splittable into m subarrays at sum <= mid

lo = 12, hi = 43

1st —> mid 27 —> [7, 12, 2, 5,|| 6, 8, 3]

iterate 的时候,在 sum >= mid 值就停下,这样就有 小于等于 mid 的数值, 这里是 26 和 16,切了 2 刀 小于 3,所以取大了



lo = 12, hi = 27

2st —> mid 18 —> [7, || 12, 2,|| 5, 6, ||8, 3]

这里切了 4 刀, 大于 3, 取小了



lo = 19, hi = 27

3st —> mid 23 —> [7, 12, 2,|| 5, 6, 8, 3]

这里切了 2 刀, 小于 3,所以取大了



lo = 19, hi = 23

4st —> mid 21 —> [7, 12, 2,|| 5, 6, 8, || 3]

这里切了 3 刀, 等于 3, 可能取大了



lo = 19, hi = 21

5st —> mid 20 —> [7, 12, || 2, 5, 6, || 8, 3]

这里切了 3 刀, 等于 3, 可能取大了



lo = 19, hi = 20

6st —> mid 19 —> [7, 12, || 2, 5, 6, || 8, 3]

这里切了 3 刀, 等于 3, 可能取大了


lo = hi = 19, return hi 19

 public int splitArray(int[] nums, int m) {
       // 1 5 9
        int sum = Arrays.stream(nums).sum();
        int max = Arrays.stream(nums).max().getAsInt();
        return binary(nums, m, sum, max);
        
    }
    // 10, 24
    // 
    
    private int binary(int[] nums, int m, int high, int low) {
        int mid = 0;
        
        while (low <= high) {
            mid = low + (high - low) / 2;
           if (valid(nums, m, mid)) {
               high = mid - 1;
           } else {
               low = mid + 1;
           }
           
        }
         return low;
    }
    
    private boolean valid(int[] nums, int m, int subArraySum) {
        int curSum = 0, count = 1;
        for (int num : nums) {
            curSum += num;
            if (curSum > subArraySum) {
                curSum = num;
                count++;
               if (count > m) {
                   return false;
               }
            }
        }
        return true;
    }
image

intern()


dp