leetcode5955.摘水果(困难,周赛)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
自己没思路,感觉下标处理太麻烦了。。。
有两种情况
1.假设人向左走 y 步,然后回到原点,再向右走 x步。
2.假设人向右走 y 步,然后回到原点,再向左走 x步。
写法:枚举x的长度即为所有情况!!!

for (int x = 0; x <= k; ++x)  {
	int y = (k - x) / 2;
	[startPos - x, startPos + y]的区间和(向右走 y 步,然后回到原点,再向左走 x步)
	[startPos - y, startPos + x]的区间和(向左走 y 步,然后回到原点,再向右走 x步)
}

方法一:二分查找下标(用稀疏区间和处理)

class Solution {
public:
    int maxTotalFruits(vector<vector<int>>& fruits, int startPos, int k) {
        
        vector<int> sum, pos;
        for (auto& each : fruits) {
        	if (sum.empty()) sum.push_back(each[1]);
            else sum.push_back(sum.back() + each[1]);
            pos.push_back(each[0]);
        }
        int it1, it2;
        int ans = 0;
        for (int x = 0; x <= k; ++x) {
            int y = (k - x) / 2; //向下取整,才能保证向右走x步
            //[startPos - x, startPos + y]区间和
            it1 = lower_bound(pos.begin(), pos.end(), startPos - x) - pos.begin();
            it2 = upper_bound(pos.begin(), pos.end(), startPos + y) - pos.begin() - 1;
            if (it2 != -1) { //这里必须加个判断,当it2等于-1时,表示该区间完全不存在,下面访问it2处的值时会越界!!!
                if (it1 == 0)  ans = max(ans, sum[it2] - 0);
                else ans = max(ans, sum[it2] - sum[it1 - 1]);
            } 
            //[startPos - y, startPos + x]
            it1 = lower_bound(pos.begin(), pos.end(), startPos - y) - pos.begin(); 
            it2 = upper_bound(pos.begin(), pos.end(), startPos + x) - pos.begin() - 1;
            if (it2 != -1) { 
                if (it1 == 0)  ans = max(ans, sum[it2] - 0);
                else ans = max(ans, sum[it2] - sum[it1 - 1]);
            } 
        }
        return ans;
    }
};

方法二:计算出取值范围内所有的区间和

class Solution {
public:
    int maxTotalFruits(vector<vector<int>>& fruits, int startPos, int k) {
        
        int _max = INT_MIN;
        for (auto& each : fruits) {
            _max = max(_max, each[0]);
        }
        vector<int> sum(_max + 1); //sum数组的下标为0-fruit[0]的最大值
        _max++;
        for (auto& each : fruits) {
            sum[each[0]] = each[1];
        }
        for (int i = 1; i < _max; ++i) {
            sum[i] = sum[i - 1] + sum[i];
        }
        int ans = 0; //如果没有在区间内的话,返回0,不能初始化为int最小值
        for (int x = 0; x <= k; ++x) {
            int y = (k - x) / 2;
            int ma, mi;

            if (startPos - x < _max) { //可能会出现左右端点都不在0-_max-1中的情况!!!
                ma = (startPos + y >= _max) ? sum[_max - 1] : sum[startPos + y];
                mi = (startPos - x == 0 || startPos - x < 0) ? 0 : sum[startPos - x - 1];
                ans = max(ans, ma - mi);
            }  

           if (startPos - y < _max) {
                ma = (startPos + x >= _max) ? sum[_max - 1] : sum[startPos + x]; //
                mi = (startPos - y == 0 || startPos - y < 0) ? 0 : sum[startPos - y - 1]; //
                ans = max(ans, ma - mi);
           }
        }
        return ans;
    }
};

易错点:
1:右端点可能会越界
2:左端点可能会越界
3:左右端点可能都会越界(因为startpos的取值范围不是0-position的最大值!!!)
4:ans初始化为0

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值