想要精通算法和SQL的成长之路 - 分割数组的最大值

想要精通算法和SQL的成长之路 - 分割数组的最大值

  • 前言
  • [一. 分割数组的最大值](#一. 分割数组的最大值)
    • [1.1 二分法](#1.1 二分法)

前言

想要精通算法和SQL的成长之路 - 系列导航

一. 分割数组的最大值

原题链接

首先面对这个题目,我们可以捕获几个关键词:

  • 非负整数。
  • 非空连续子数组。

那么我们假设分割后的子数组,和的最大值是M,对应分割的子数组个数为N。他们之间必然存在以下关系:

  • 分割的子数组个数 N 越多,对应的和最大值 M 也就越小。
  • 分割的子数组个数 N 越少,对应的和最大值 M 也就越大。

那么我们以每组和的最大值作为切入点,案例如下:

  • 设置 数组各自和的最大值 为 20,此时分割依然是 [7, 2, 5, | 10, 8],此时分割的数组数为2。
  • 设置 数组各自和的最大值 为 19,此时分割依然是 [7, 2, 5, | 10, 8],此时分割的数组数为2。
  • 设置 数组各自和的最大值 为 18,此时分割依然是 [7, 2, 5, | 10, 8],此时分割的数组数为2。
  • 设置 数组各自和的最大值 为 17,此时分割就变成了 [7, 2, 5, | 10, | 8],此时分割的数组数为3。

而我们题目要求分割组数是2,那么满足这个条件的几种情况,我们再取最大和最小的情况,最终得到结果是18。

1.1 二分法

二分的目标对象是什么?我们可以二分:数组各自和的最大值。那么二分法,就应该有初始区间:

  • left:可以是当前数组的最大元素值。(单个元素一组)
  • right:可以是当前数组的总和。(所有元素成一组)

那么我们二分后取得 mid

java 复制代码
int mid = left + (right - left) / 2;

接下来我们就要对数组进行分组计算了,对数组从左往右按顺序分组,使得分组后的各个子数组和不能超过mid。我们可以编写个helper函数:

java 复制代码
public int helper(int[] nums, int maxGroupSum) {
    // 分组数最小是1
    int res = 1;
    int curSum = 0;
    for (int num : nums) {
        // 如果加入当前元素会导致和超过限制,那么就另外再分一组
        if (curSum + num > maxGroupSum) {
            res++;
            curSum = 0;
        }
        curSum += num;
    }
    return res;
}

我们计算好分组后的个数groupNum之后,就需要和题目传入的k进行对比:

  • groupNum > k : 说明数组各自和的最大值 还是小了,我们应该调大数组各自和的最大值 。即left = mid +1
  • 反之:right = mid;

最终代码如下:

java 复制代码
public int splitArray(int[] nums, int k) {
    int max = 0, sum = 0;
    for (int num : nums) {
        max = Math.max(max, num);
        sum += num;
    }
    int left = max, right = sum;
    while (left < right) {
        int mid = left + (right - left) / 2;
        // 如果分组数比 k 还要大,说明每个分组的和最大值还是小了
        int groupNum = helper(nums, mid);
        if (groupNum > k) {
            left = mid + 1;
        } else {
            right = mid;
        }
    }
    return left;
}

public int helper(int[] nums, int maxGroupSum) {
    // 分组数最小是1
    int res = 1;
    int curSum = 0;
    for (int num : nums) {
        // 如果加入当前元素会导致和超过限制,那么就另外再分一组
        if (curSum + num > maxGroupSum) {
            res++;
            curSum = 0;
        }
        curSum += num;
    }
    return res;
}
相关推荐
Amarantine、沐风倩✨3 分钟前
设计一个监控摄像头物联网IOT(webRTC、音视频、文件存储)
java·物联网·音视频·webrtc·html5·视频编解码·七牛云存储
路在脚下@1 小时前
spring boot的配置文件属性注入到类的静态属性
java·spring boot·sql
森屿Serien1 小时前
Spring Boot常用注解
java·spring boot·后端
苹果醋32 小时前
React源码02 - 基础知识 React API 一览
java·运维·spring boot·mysql·nginx
Hello.Reader3 小时前
深入解析 Apache APISIX
java·apache
菠萝蚊鸭3 小时前
Dhatim FastExcel 读写 Excel 文件
java·excel·fastexcel
旭东怪3 小时前
EasyPoi 使用$fe:模板语法生成Word动态行
java·前端·word
007php0073 小时前
Go语言zero项目部署后启动失败问题分析与解决
java·服务器·网络·python·golang·php·ai编程
∝请叫*我简单先生3 小时前
java如何使用poi-tl在word模板里渲染多张图片
java·后端·poi-tl
ssr——ssss3 小时前
SSM-期末项目 - 基于SSM的宠物信息管理系统
java·ssm