leecode-每日一题-2106. 摘水果
思路:
- 路径最多有一次折返(假设有更多次的往返,在相同左或右边界时,区间小于0次或1次往返)
2.二分查找找到每次水果的左右边界+前缀和数组根据左右边界计算区域内结果。
int findR(int** fruits, int fruitsSize, int target){int left = 0, right = fruitsSize;if(fruits[fruitsSize-1][0] < target) return fruitsSize;while(left < right){int mid = left + (right-left)/2;if(fruits[mid][0] < target){left = mid+1;}else{right = mid;}}return left;
}
int findL(int** fruits, int fruitsSize, int target){int left = 0, right = fruitsSize-1;if(fruits[0][0] > target) return -1;while(left < right){int mid = left + (right-left+1)/2;if(fruits[mid][0] > target){right = mid-1;}else{left = mid;}}return right;
}
int maxTotalFruits(int** fruits, int fruitsSize, int* fruitsColSize, int startPos, int k) {if(fruitsSize == 0) return 0;int left = 0, right = 0;// 左边界的索引left = findR(fruits, fruitsSize, startPos-k);// 右边界的索引right = findL(fruits, fruitsSize, startPos+k);if(right < left ) return 0;int n = right-left+2;int prefix[n];prefix[0] = 0;for(int i=1; i<n; i++){prefix[i] = prefix[i-1]+fruits[left + i - 1][1];}int base = left;int res = 0;int i = left;int end = right;// 向左while(i < fruitsSize && fruits[i][0] < startPos){left = i;int ridex = fruits[i][0]+k-(startPos-fruits[i][0]);ridex = ridex > startPos ? ridex : startPos;// 右边界right = findL(fruits, fruitsSize, ridex);// 更新结果int tmp = right < left ? 0 : prefix[right+1-base]-prefix[left-base];res = tmp > res ? tmp : res;i++;}// 向右while(i < fruitsSize && i <= end){right = i;int lidex = fruits[i][0] - (k - (fruits[i][0]-startPos));lidex = lidex < startPos ? lidex : startPos;// 左边界left = findR(fruits, fruitsSize, lidex);// 更新结果int tmp = right < left ? 0 : prefix[right+1-base]-prefix[left-base];res = tmp > res ? tmp : res;i++;}return res;
}