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