leetcode 1802 线性变化问题 模拟+二分

解法一:模拟
此题的模拟分为两个阶段。首先把地面铺满,这样一定是满足要求的,然后在index处开始累加即可。在第一阶段咱们直接模拟,index处的值每次加一,这个值减去2就是他每次辐射到的范围。当两边都被辐射到,即进入第二阶段后,可以直接用简单除法完成。

class Solution {
public:
    int maxValue(int n, int index, int maxSum) {
        int sum = n;
        int ret = 1;
        while(1)
        {
            ret += 1;
            sum += 1;
            sum += min(index, ret-2);
            sum += min(n-index-1, ret-2);
            if(sum > maxSum)return ret-1;
            
            // 提前终止
            if(index < ret-2 && n-index-1 < ret-2)
            {
                return (maxSum-sum)/n + ret;
            }
        }
    }
};

解法二:二分
接下来考虑另一种思路,给定一个index位置的值,我们能否判断当前和?答案是肯定的。这个计算相对并不复杂。因此,我们就可以用二分来解决这个问题,不断缩短区间直到找到目标。
代码这里做了一个简化,即计算左边还是右边都是一个区间问题,考虑当前最大值和区间长度即可。

typedef long long ll;
class Solution {
public:
    ll partSum(ll x, ll len)
    {
        if(len <= 0)return 0;
        if(len <= x)
        {
            ll min_val = x-len+1;
            return (min_val+x)*len/2;
        }
        return (1+x)*x/2 + len-x;
    }

    ll sum(int x, int n, int index)
    {
        return x + partSum(x-1, index) + partSum(x-1, n-index-1);
    }

    int maxValue(int n, int index, int maxSum) {
        // 进行二分查找
        int l=1, r=maxSum;

        while(l<r)
        {
            int mid = l + ceil((r-l)/2.0);
            if(sum(mid, n, index) > maxSum)r = mid-1;
            else l = mid;
        }

        return l;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值