2023.01/1802. 有界数组中指定下标处的最大值

1802. 有界数组中指定下标处的最大值


题意:

给你三个正整数 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

解题思路:

  • 题意注意点:
    • abs(nums[i] - nums[i+1]) <= 1 ,其中 0 <= i < n-1
    • nums 中所有元素之和不超过 maxSum
    • nums[index] 的值被 最大化
    • 返回你所构造的数组中的 nums[index]
  • 获取信息:
    • 目的就是在尽可能接近 maxSum的情况下,获取最大值的num[index]
    • num[index]要尽可能的大,那么其它数就要尽可能的小
    • num[index]确定的情况下,它的数组的其它数要尽可能的小,又因为左右的绝对值之差不能超过1,所以,其它数其实就是递减的
    • 既然其它数都是确定的,那么总和就能算出来.
    • 现在的问题就是怎么确定num[index],既然没办法直接获得,那么我们就只能考猜.猜它的数是什么.
    • 一般跟猜数联系起来的,就是二分寻找法,这样就可以减少猜数的时间复杂度.
  • 思路:
    • 现在思路就很清晰的,利用二分确定nums[index],让数组的总和尽量靠近maxSum
    • 怎么算数组的总和.因为前面说过他是递减的,所以用求和公式直接求解就行
  • 麻烦点:
    • 要判断数的个数是否大于nums[index],如果小于说明还没到1,如果大于那么剩下的空位要补1;
    • 数组的下标有左右两边,所以要分别做判断
  • 小陷阱:
    • 总和要用long long,否则会溢出

代码:

class Solution {
public:
long long getNum(long long n)		//求和公式
{
	return (1 + n) * n / 2;		
}

long long getSum(int index,int num,int n)		
{
	int left = index;			//下标左边数的个数		

	int right = n - index - 1;		//下标右边数的个数			


	//总和
	long long sum = num;		
	//左边之和
	int t = num - 1;
	if (left > 0)
	{
		if (left < num)	//数的个数小于nums[index],直接用两次计算求总和
		{
			sum += getNum(t) - getNum(t - left);		
		}
		else			//数的个数大于nums[index],其他空位要补1
		{
			sum += getNum(t);
			sum += left - t;		//补1
		}
	}


	//右边之和,与左边一致
	if (right > 0)
	{
		if (right < num)
		{
			sum += getNum(t) - getNum(t - right);
		}
		else
		{
			sum += getNum(t);
			sum += right - t;
		}
	}



	return sum;
}


int maxValue(int n, int index, int maxSum)
{
	if (n == maxSum)		//如果刚好相等,那么不用算了肯定为1
		return 1;

	int left = 0;
	int right = maxSum;

	while (left <= right)			//二分法寻找nums[index]
	{
		int mid = (right - left) / 2 + left;		
		long long sum = getSum(index, mid, n);		//获取数组总和,记得用long long
		if (sum > maxSum)
			right = mid - 1;
		else if (sum < maxSum)
			left = mid + 1;
		else
			return mid;
	}

	return right;
}
};

你可能感兴趣的:(算法,leetcode,数据结构)