自己没思路,感觉下标处理太麻烦了。。。
有两种情况:
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