思路:
首先根据题目要求,相邻数字的差距不能大于1,所以数组中的元素分布一定是以最大元素位置为塔顶,向两边发散的金字塔状,最小值为1,这样的结构能保证数组元素和一定是最小的(只有1是重复元素);那么问题就变成一个找最大值numMax的问题,对于该问题,可用分治法实现;
首先最大值一定在1到maxSum之间,那么为了提高效率,肯定采用分治法;在分治的过程中,每代入一个数字就对该数组元素和进行一个判断直到找到一个最大的满足条件的numMax
原题链接:https://leetcode.cn/problems/maximum-value-at-a-given-index-in-a-bounded-array/
给你三个正整数 n、index 和 maxSum 。你需要构造一个同时满足下述所有条件的数组 nums(下标 从 0 开始 计数):
nums.length == n
nums[i] 是 正整数 ,其中 0 <= i < n
abs(nums[i] - nums[i+1]) <= 1 ,其中 0 <= i < n-1
nums 中所有元素之和不超过 maxSum
nums[index] 的值被 最大化
返回你所构造的数组中的 nums[index] 。
注意:abs(x) 等于 x 的前提是 x >= 0 ;否则,abs(x) 等于 -x 。
输入:n = 4, index = 2, maxSum = 6
输出:2
解释:数组 [1,1,2,1] 和 [1,2,2,1] 满足所有条件。不存在其他在指定下标处具有更大值的有效数组。
输入:n = 6, index = 1, maxSum = 10
输出:3
1 <= n <= maxSum <= 109
0 <= index < n
class Solution {
public:
//思路一:贪心 + 分治 实现最大化
/*
首先在指定位置为最大值,按照贪心思路:从最大值向两边发散,随坐标元素值-1直到1or边界
重点是如何找到那个最大的maxNum能够实现贪心同时sum
//二分法,不断的寻找能够满足条件的最大的num
int maxValue(int n, int index, int maxSum) {
int left=1;
int right=maxSum;
while(left<right){
int mid=(left+right+1)/2;
//使用二分法,直到找到最大的满足条件的数
if(isValid(mid,n,index,maxSum)){
left=mid;
}
else{
right=mid-1;
}
}
return left;
}
// 计算设定的最大值和最大值左右的等差数列是否能够满足条件即不大于最大值maxNum
int isValid(int mid,int n,int index,int maxSum){
return sumNum(mid,index)+sumNum(mid,n-index-1)+mid<=maxSum;
}
// 计算最大值为max且单边长度为length的等差数组元素和
long sumNum(int max,int length){
if(max>length+1){
return(long)(max-length+ max-1)*length/2;
}
// 等差无法占满数组,边界之外的值为1
else{
int ones=length-(max-1);
return (long)max*(max-1)/2+ones;
}
}
};