【LeetCode 1802. 有界数组中指定下标处的最大值 】- JavaScript(双指针+二分)

222 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情


说明:文章部分内容及图片出自网络,如有侵权请与我本人联系(主页有公众号:小攻城狮学前端)

作者:小只前端攻城狮、 主页:小只前端攻城狮的主页、 来源:掘金

GitHub:P-J27、 CSDN:PJ想做前端攻城狮

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


【LeetCode 2024.考试的最大困扰度 】- JavaScript(双指针+滑动窗口)

题目描述

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

思路分析

此题本来想用等差数列去解决,结果碰上有空位放了0个砖块,以及总小于结果值的各种问题。 这个三角型,每层新加的元素之和为n^2,减去边界未增加的砖块,即目前所用的砖块总数,对剩余的再分配……

二分

二分搜索答案,答案的上界为maxSum,下界为1。若nums[index] = x能使数组的最小和小于等于maxSum,那么小于x的值也满足该条件,所以二分时X要上取整。而且整体应该是从大的值往小的逼近(high->low),即二分时high = mid-1,low = mid

var maxValue = function(n, index, maxSum) {
    const diff = maxSum - n;
    let high = 1e9, low = 0, mid, cur;
    while(low < high) {
        mid = Math.floor((high + low) / 2);
        cur = val(mid, index, n);
        if(cur === diff) {
            return 1 + mid;
        }
        else if(cur < diff) {
            low = mid + 1;
        }
        else {
            high = mid;
        }
    }
    return low;
};
​
const val = (x, index, len) => {
    if(x <= 1) return x;
    let res = 0;
    if(x <= index + 1) {
        res += Math.floor((x - 1) * x / 2);
    }
    else {
        res += Math.floor((2 * x - index - 1) * index / 2);
    }
    if(x <= len - index) {
        res += Math.floor((x - 1) * x / 2);
    }
    else {
        res += Math.floor((2 * x - len + index) * (len - index - 1) / 2);
    }
    return res + x;
}
​
双指针暴力模拟

分析一波:这题最关键在于理解题意,结合几个限定条件,绘图我们可以发现要算出最大值,就要把图形画成宝塔的形状,才有可能找到最大值,但是存在底边宽度的限制,塔顶的位置不一定在中心,所以我们去找每层宽度的值,进行累加即可

class Solution {
public:
    int maxValue(int n, int index, int maxSum) {
        int left = index, right = index;     
        int rest = maxSum - n, ans = 1;        
        while(left > 0 || right < n - 1) {     
            if(rest - (right - left + 1) >= 0) {  
                ans++;                             
                rest -= right - left + 1;           
            } else break;                           
            left = left == 0? 0 : left -1;         
            right = right == n-1? n-1 : right + 1;
        }
        ans += rest / n;                           
        return ans;
   } 
};

感谢阅读,希望能对你有所帮助,文章若有错误或者侵权,可以在评论区留言或在我的主页添加公众号联系我。

写作不易,如果觉得不错,可以「点赞」+「评论」 谢谢支持❤