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

该问题是一个关于算法的编程题,目标是构造一个长度为n的正整数数组,数组相邻元素之差不超过1,且数组所有元素之和不超过maxSum,同时要最大化指定下标(index)处的数值。解决方案是使用二分搜索法来寻找nums[index]的最大可能值。当二分查找的中间值mid作为nums[index]时,计算数组总和是否不超过maxSum,根据比较结果调整搜索范围,最终找到满足条件的最大值。
摘要由CSDN通过智能技术生成

题目链接

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

题目描述

给你三个正整数 n、index 和 maxSum 。你需要构造一个同时满足下述所有条件的数组 nums(下标 从 0 开始 计数):

  • n u m s . l e n g t h = = n nums.length == n nums.length==n
  • nums[i] 是 正整数 ,其中 0 <= i < n
  • a b s ( n u m s [ i ] − n u m s [ i + 1 ] ) < = 1 abs(nums[i] - nums[i+1]) <= 1 abs(nums[i]nums[i+1])<=1 ,其中 0 < = i < n − 1 0 <= i < n-1 0<=i<n1
  • nums 中所有元素之和不超过 maxSum
  • nums[index] 的值被 最大化

返回你所构造的数组中的 nums[index] 。

示例 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 < = m a x S u m < = 1 0 9 1 <= n <= maxSum <= 10^9 1<=n<=maxSum<=109
0 < = i n d e x < n 0 <= index < n 0<=index<n

题目分析:

用例2构成的数组可能为 nums = [2,3,2,1,1,1] , 数组的和 sum = 8 < 10 满足要求。当nums[index] = 4时,
nums = [3,4,3,2,1,1] , 数组的和 sum = 14 > 10 不满足要求。所以最终返回的nums[index] 的最大值为 3。
我就可以使用二分的方式来寻求nums[index] 的最大值。此时二分的值为 mid , 指定此时nums[index] 的值为mid,如果此时数组的和 sum <= maxSum , l = mid(因为我们要求的是nums[index] 的最大值);如果 sum > maxSum 说明mid选择的值太大了,需要缩小,故 r = mid - 1。

边界问题:

在这里插入图片描述

右边也是类似的情况

  • 时间复杂度: O ( l o g n ) O(logn) O(logn)

C++代码

class Solution {
public:
    long long get(int b,int n){
        return (b - n + 1 + b) * 1LL * n / 2;
    }
    int maxValue(int n, int index, int maxSum) {
        int l = 1,r = maxSum;
        while(l<r){
            int mid = (l + r + 1) >> 1;
            long long sum = 0LL;
            if(index + 1 >= mid){
                sum += get(mid,mid);
                sum += index + 1 - mid;
            }
            else{
                int len = index + 1;
                sum += get(mid,len);
            }

            if(n - index >= mid){
                sum += get(mid,mid);
                sum += n - index - mid;
            }
            else{
                int len = n - index;
                sum += get(mid,len);
            }
            sum -= mid;

            if(sum <= maxSum) l = mid;
            else r = mid - 1;
        }
        return l;
    }
};

Java代码

class Solution {

    //返回 最后一项是 m 数量是cnt 的等差数列的和(第一项就是 m - cnt + 1)
    //用 long 是为了避免溢出
    private long get(int m,int cnt){
        return (m - cnt + 1 + m) * 1L * cnt / 2;
    }
    public int maxValue(int n, int index, int maxSum) {
        int l = 1,r = maxSum;
        while(l<r){
            int mid = (l + r + 1) >> 1;
            long sum = 0L;
            
            //此时的cnt 是包括 mid 在内的左边的元素个数
            int cnt = index + 1;
            if(cnt >= mid){
                sum += get(mid,mid);
                sum += cnt - mid;
            }
            else sum += get(mid,cnt);

            //此时的cnt 是包括mid在内的右边的元素个数
            cnt = n - index;
            if(cnt >= mid){
                sum += get(mid,mid);
                sum += cnt - mid;
            }
            else sum += get(mid,cnt);

            //因为加了2个mid 所以需要减去1个
            sum -= mid;
            
            //如果此时的sum <= maxSum 说明此时的mid是符合条件的 用mid来更新 l
            if(sum <= maxSum) l = mid;
            //不满足的话 包括mid在内的右边的数都会不满足,所以让 r 更新为 mid - 1 
            else r = mid - 1;
        }
        return l;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值