摘水果

x坐标轴上分配了水果的位置(升序)和个数
给你一个开始位置和步数,可以选择往左或往右,返回可以摘到的最大水果数

1. 二分查找+前缀和+滑动窗口

枚举先左后右和先右后左两种情况下的左右边界,利用二分和前缀和快速求值

class Solution {
public:
    int maxTotalFruits(vector<vector<int>>& fruits, int startPos, int k) {
        int n = fruits.size();
        vector<int> presum(n + 1);//前缀和
        vector<int> indices(n);//单独用来二分
        for (int i = 0; i < n; i++) {
            presum[i + 1] = presum[i] + fruits[i][1];
            indices[i] = fruits[i][0];
        }
        int res = 0;
        for (int x = 0; x <= k / 2; x++) {
            /* 向左走 x 步,再向右走 k - x 步 */
            int y = k - 2 * x;//往右的距离
            int left = startPos - x;//左边界
            int right = startPos + y;//右边界
            int start = lower_bound(indices.begin(), indices.end(), left) - indices.begin();//左闭
            int end = upper_bound(indices.begin(), indices.end(), right) - indices.begin();//右开
            //这里end相当于end的前一个位置,即所能到达右侧最远位置,其前缀和
            res = max(res, presum[end] - presum[start]);
            /* 向右走 x 步,再向左走 k - x 步 */
            y = k - 2 * x;
            left = startPos - y;
            right = startPos + x;
            start = lower_bound(indices.begin(), indices.end(), left) - indices.begin();
            end = upper_bound(indices.begin(), indices.end(), right) - indices.begin();
            res = max(res, presum[end] - presum[start]);
        }
        return res;
    }
};
posted @ 2023-05-04 01:07  失控D大白兔  阅读(19)  评论(0编辑  收藏  举报