想要精通算法和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;
}
相关推荐
计算机毕设指导611 分钟前
基于 SpringBoot 的作业管理系统【附源码】
java·vue.js·spring boot·后端·mysql·spring·intellij-idea
Gu Gu Study12 分钟前
枚举与lambda表达式,枚举实现单例模式为什么是安全的,lambda表达式与函数式接口的小九九~
java·开发语言
Chris _data15 分钟前
二叉树oj题解析
java·数据结构
牙牙70521 分钟前
Centos7安装Jenkins脚本一键部署
java·servlet·jenkins
დ旧言~27 分钟前
【高阶数据结构】图论
算法·深度优先·广度优先·宽度优先·推荐算法
paopaokaka_luck28 分钟前
[371]基于springboot的高校实习管理系统
java·spring boot·后端
张彦峰ZYF32 分钟前
投资策略规划最优决策分析
分布式·算法·金融
以后不吃煲仔饭41 分钟前
Java基础夯实——2.7 线程上下文切换
java·开发语言
进阶的架构师42 分钟前
2024年Java面试题及答案整理(1000+面试题附答案解析)
java·开发语言
The_Ticker1 小时前
CFD平台如何接入实时行情源
java·大数据·数据库·人工智能·算法·区块链·软件工程