2019.11.15 #程序员笔试必备# LeetCode 从零单刷个人笔记整理(持续更新)
github:https://github.com/ChopinXBP/LeetCode-Babel
经典的最大和最小问题,也是2019年携程校招后台开发执行任务题的母题。
根本思路是桶思想+二分查找+贪心,将分割的子数组看成很多个buckets,子数组的最大和为桶容量。题目要求给定桶数量下使桶容量最大值最小的桶容量。
我们可以对分隔数组最大和(最大桶容量)进行二分查找,范围为[数组最大元素值,数组元素和]。
每次查找时判断在当前桶数量m和最大桶容量mid限定下,数组能否完成分割。判断方式可以用贪心策略从前往后将每个桶装满最大容量求桶数。
最终只要找出能够完成分割的最小桶容量即可。
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.
给定一个非负整数数组和一个整数 m,你需要将这个数组分成 m 个非空的连续子数组。设计一个算法使得这 m 个子数组各自和的最大值最小。
示例:
输入:
nums = [7,2,5,10,8]
m = 2
输出:
18
解释:
一共有四种方法将nums分割为2个子数组。
其中最好的方式是将其分为[7,2,5] 和 [10,8],
因为此时这两个子数组各自的和的最大值为18,在所有情况中最小。
注意:
数组长度 n 满足以下条件:
1 ≤ n ≤ 1000
1 ≤ m ≤ min(50, n)
/**
*
* 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.
* 给定一个非负整数数组和一个整数 m,你需要将这个数组分成 m 个非空的连续子数组。设计一个算法使得这 m 个子数组各自和的最大值最小。
*
*/
public class SplitArrayLargestSum {
//最大和最小问题
public int splitArray(int[] nums, int m) {
long max = Integer.MIN_VALUE;
long sum = 0;
for(int num : nums){
max = num > max ? num : max;
sum += num;
}
//对分隔数组最大和(最大桶容量)进行二分查找,范围为[数组最大元素值,数组元素和]
long begin = max;
long end = sum;
while(begin < end){
long mid = (begin + end) >> 1;
//判断在当前桶数量m和最大桶容量mid限定下,数组能否完成分割
if(canBeSplit(nums, m, mid)){
end = mid;
}else{
begin = mid + 1;
}
}
return (int)begin;
}
private boolean canBeSplit(int[] nums, int m, long maxSum){
long curSum = 0;
long curNum = 0;
for(int i = 0; i < nums.length; i++){
curSum += nums[i];
if(curSum > maxSum){
curSum = nums[i];
curNum++;
}else if(curSum == maxSum){
curSum = 0;
curNum++;
}
if(curNum > m){
return false;
}
}
if(curSum > 0){
curNum++;
}
return curNum <= m;
}
}
#Coding一小时,Copying一秒钟。留个言点个赞呗,谢谢你#
扫描二维码关注公众号,回复:
8567443 查看本文章