1300.转变数组后最接近目标值的和
思路
class Solution {
public:
int findBestValue(vector<int>& arr, int target) {
int right = INT_MIN;
int left = 0;
for (auto& v : arr) {
//找到最大的数,作为右指针
right = max(right, v);
}
//二分法,找到第一个使得sum大于target的数
while (left < right) {//O(LogN)
int mid = left + (right - left) / 2;
int sum = calculate(arr, mid);//O(N)
if (sum < target) {
//严格小于,一定不是解
left = mid + 1;
}
else if (sum == target)
return mid;
else// 大于的可能是解
right = mid;
}
// 比较阈值线分别定在 left - 1 和 left 的时候与 target 的接近程度
int sum1 = calculate(arr, left - 1);
int sum2 = calculate(arr, left);
if (target - sum1 <= sum2 - target) {
return left - 1;
}
return left;
}
//计算数组以threshold为阈值的和
int calculate(vector<int>& arr, int threshold) {
int sum = 0;
for (auto& v : arr) {
sum += min(v, threshold);
}
return sum;
}
};
复杂度
1482.制作m束花所需的最少天数
要用二分法,不然超时
对于当前天数mid,贪心计算有多少个连续的小于等于mid的k天,假设有cnt个连续k天,判断cnt是否大于等于m即可
class Solution {
public:
bool check(vector<int>&a,int m,int k,int mid){
int n=a.size();
int cnt=0;
int len=0;
for(int i=0;i<n;i++){
if(a[i]<=mid){
len++;
if(len==k){
cnt++;
len=0;
}
}else{
len=0;
}
}
return cnt>=m;
}
int minDays(vector<int>& a, int m, int k) {
int n=a.size();
int l=1,r=1e9;//题目说明1 <= bloomDay[i] <= 10^9
int ans=-1;
while(l<=r){
int mid=(l+r)/2;
if(check(a,m,k,mid)){
ans=mid,r=mid-1;
}else{
l=mid+1;
}
}
return ans;
}
};
复杂度
时间: O ( N l o g M ) O(NlogM) O(NlogM), N = a . s i z e ( ) N=a.size() N=a.size(), M = 1 0 9 M=10^9 M=109.