【每日一题Day77】LC1802有界数组中指定下标处的最大值 | 二分查找+贪心

44 篇文章 0 订阅
14 篇文章 0 订阅

有界数组中指定下标处的最大值【LC1802】

You are given three positive integers: n, index, and maxSum. You want to construct an array nums (0-indexed) that satisfies the following conditions:

  • nums.length == n
  • nums[i] is a positive integer where 0 <= i < n.
  • abs(nums[i] - nums[i+1]) <= 1 where 0 <= i < n-1.
  • The sum of all the elements of nums does not exceed maxSum.
  • nums[index] is maximized.

Return nums[index] of the constructed array.

Note that abs(x) equals x if x >= 0, and -x otherwise.

按专题训练效果就是不错

  • 思路:

    • 由于当指定下标处的数值越大,数组总和也越大,因此可以通过二分查找搜索指定下标处的最大值。
      • 因为数组中的数值有要求:相邻元素的绝对值不超过1,数组中的元素均大于等于1,并尽可能使指定下标处的元素最大
      • 当数组和一定时,要使指定下标处的数值最大,应以该位置为中心,相邻位置以1为间隔梯度下降,直至数值等于1【贪心获得数组和】
      • 因此指定下标的数值固定时,数组总和固定【单调性】
    • 因此可以将题意转化为当数组总和小于等于maxSum时,寻找指定下标处数值的最大值 y y y,二分查找的下限为1,上限为maxSum
  • 实现

    • 当二分查找指定下标处的数值 y y y时,需要判断数组总和是否小于等于maxSum,如果数组总和小于等于maxSum,那么我们可以增大最大数值;如果不能,那么减小最大数值
    class Solution {
        public int maxValue(int n, int index, int maxSum) {
            if (maxSum == n) return 1;
            int l = 1, r = maxSum;
            int ans = 0;
            while (l <= r){
                int mid = (l + r) / 2;
                if (check(mid, index, n, maxSum)){
                    ans = mid;
                    l = mid + 1;
                }else{
                    r = mid - 1;
                }
            }
            return ans;
    
        }
        public boolean check(int max, int index, int n, int maxSum){
            int sum = max;
            int l = index, r = index;
            int cur = max;
            while (--l >= 0 && --cur > 1){
                sum += cur;
                if (sum > maxSum){
                    return false;
                }
            }
            sum += l + 1;
            cur = max;
            while (++r < n && --cur > 1){
                sum += cur;
                if (sum > maxSum){
                    return false;
                }
            }
            sum += (n - r);
            return sum <= maxSum;
        }
    }
    
    • 复杂度
      • 时间复杂度: O ( n l o g C ) O(nlogC) O(nlogC) n n n是数组的长度,C是maxSum。求出数组和需要的时间复杂度为 O ( n ) O(n) O(n),二分查找的时间复杂度是 O ( l o g C ) O(logC) O(logC)
      • 空间复杂度: O ( 1 ) O(1) O(1)
  • 优化判断过程:根据等差数列性质求和

    class Solution {
        public int maxValue(int n, int index, int maxSum) {
            int left = 1, right = maxSum;
            while (left < right) {
                int mid = (left + right + 1) / 2;
                if (valid(mid, n, index, maxSum)) {
                    left = mid;
                } else {
                    right = mid - 1;
                }
            }
            return left;
        }
    
        public boolean valid(int mid, int n, int index, int maxSum) {
            int left = index;
            int right = n - index - 1;
            return mid + cal(mid, left) + cal(mid, right) <= maxSum;
        }
    
        public long cal(int big, int length) {
            if (length + 1 < big) {
                int small = big - length;
                return (long) (big - 1 + small) * length / 2;
            } else {
                int ones = length - (big - 1);
                return (long) big * (big - 1) / 2 + ones;
            }
        }
    }
    
    作者:力扣官方题解
    链接:https://leetcode.cn/problems/maximum-value-at-a-given-index-in-a-bounded-array/solutions/2042360/you-jie-shu-zu-zhong-zhi-ding-xia-biao-c-aav4/
    来源:力扣(LeetCode)
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
    
    • 复杂度
      • 时间复杂度: O ( l o g C ) O(logC) O(logC) n n n是数组的长度,C是maxSum。求出数组和需要的时间复杂度为 O ( 1 ) O(1) O(1),二分查找的时间复杂度是 O ( l o g C ) O(logC) O(logC)
      • 空间复杂度: O ( 1 ) O(1) O(1)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值