哈喽,兄弟们,今天遇到非常有意思的一道题目,设计非常巧妙,非常有技巧性,来跟大家分享一下:
一:题目描述:
二:题目分析:
题目描述的非常清晰易懂,大概就是给你一个数组,你可以操作无限次数,每次找到一个下标为i的数字,这个数字必须不是第一个数字,然后执行该数字减一,同时该下标的前一位置的数字加一,操作无限次数,然后找出最大的数字 ,并且在全部数字中不存在比该数字更小的最大值。拿到该题目最暴力的解法就是:单独写出一个方法,每次循环找出最大值的下标,然后在数组中进行操作,在最大数字的基础上执行减1操作,然后在前一个位置的数字进行加一操作,一次循环遍历,代码如下:
但是由于数据量的原因,超时。
这道题目就好比层次不齐的山峰,要想其可能的将山峰变得平整,就是把高的部分填入低的部分。这道题目一样,仔细分析,题目说白了就是找到一个基准,假设为x,遍历时,假如该数字大于x,则需要把多余的部分进行存储起来,因为这部分是要较小的数字进行分摊的,同样假如一个数字小于等于x,那么代表这个数字没有超过基准,可以分担超过基准数字的部分。 问题来了,怎么不断的寻找合适的基准的,答案就是二分,通过不断的调整中间值,来缩小范围。
class Solution {
public int minimizeArrayValue(int[] nums) {
int left = nums[0],right = 1000000000;
while(left < right) {
long buff = 0;
boolean flag = true;
int x = (right - left) / 2 + left;
for(int i = 0;i < nums.length;i++) {
if(nums[i] > x) {
buff -= (nums[i] - x);
}else {
buff += (x - nums[i]);
}
if(buff < 0) {
flag = false;
break;
}
}
if(flag) {
right = x;
}else {
left = x + 1;
}
}
return left;
}
}
假如看不懂的兄弟们,可以参考一下该视频:【LeetCode】2439. Minimize Maximum of Array_哔哩哔哩_bilibili