[LeetCode每日一题]2555. 两个线段获得的最多奖品

本文本质上为本人对力扣题解区灵茶山艾符的题解的理解

看题目条件,给定一个非递减数组表示奖品位置,求两条线段所能覆盖的最大奖品数.先将题目简化,假设只有一条线段,就变成的标准的滑动窗口题.在此基础上,我们要解决的就是求出再加一条线段所能覆盖的奖品数.

先看简化的问题,我们用滑动窗口过一遍数组即可,要注意题目给出的数组表示奖品所在位置,而非x轴上每个位置的奖品个数,所以计算线段长度的公式为prizePositions[r] - prizePositions[l].

    int l = 0, ans = 0;
    for (int r = 0; r < n; r++) {
        while (prizePositions[r] - prizePositions[l] > k) {
            l++;
        }
        ans = max(ans, r - l + 1);
    }

这样我们就完成了这道题的二分之一,剩下的就是解决如何找到另外一条线段的最大覆盖数,即长度为k的线段所能覆盖的次大奖品数.上面这段代码其实已经求出了在x轴上每个位置所能覆盖的最大奖品数(此位置指线段右端点位置),既然我们找到最大的线段,在这条线段之前的最大不就是次大的线段了吗.

认识到了这一点,问题就迎刃而解啦.我们创建一个数组来存储每个位置的最大覆盖数即可.

    int maximizeWin(vector<int>& prizePositions, int k) {
        int n = prizePositions.size();
        if (2 * k + 1 >= prizePositions[n - 1] - prizePositions[0]) {
            return n;
        }
        vector<int> mx(n + 1);
        int l = 0, ans = 0;
        for (int r = 0; r < n; r++) {
            while (prizePositions[r] - prizePositions[l] > k) {
                l++;
            }
            ans = max(ans, mx[l] + r - l + 1);
            mx[r + 1] = max(mx[r], r - l + 1);
        }
        return ans;
    }

 需要注意,mx[x]描述的其实是(x - 1)之前的最大奖品数,但在l = 0时会出现负数,所以我们将mx的大小设为(n + 1),即可避免负数的产生.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值