1300. 转变数组后最接近目标值的数组和
给你一个整数数组 arr 和一个目标值 target ,请你返回一个整数 value ,使得将数组中所有大于 value 的值变成 value 后,数组的和最接近 target (最接近表示两者之差的绝对值最小)。
如果有多种使得和最接近 target 的方案,请你返回这些整数中的最小值。
请注意,答案不一定是 arr 中的数字。
示例 1:
输入:arr = [4,9,3], target = 10
输出:3
解释:当选择 value 为 3 时,数组会变成 [3, 3, 3],和为 9 ,这是最接近 target 的方案。
示例 2:
输入:arr = [2,3,5], target = 10
输出:5
示例 3:
输入:arr = [60864,25176,27249,21296,20204], target = 56803
输出:11361
思路:
先对数组arr进行排序,然后遍历数组,返回值应满足当返回值x小于等于当前遍历值时,x=(target-未转变数的和)/已转变数个数。x为小数时应该四舍五入。
代码:
int cmpfunc (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
int findBestValue(int* arr, int arrSize, int target){
qsort(arr,arrSize,sizeof(int),cmpfunc);
int total=0;
for(int i=0;i<arrSize;i++){
int res=(target-total)/(arrSize-i);
if(res<=arr[i]){
double emm=(double)(target-total)/(arrSize-i);
if(emm-res>0.5)//四舍五入
return res+1;
else
return res;
}
total=arr[i]+total;
}
return arr[arrSize-1];
}
leetcode标准答案:
int GetSum(int* arr, int arrSize, int val, int target, int flag)
{
int sum = 0;
for(int i = 0; i < arrSize; i++) {
sum += arr[i] > val ? val : arr[i];
if(sum >= target && flag == 1) {
break;
}
}
return sum;
}
int GetDiff(int* arr, int arrSize, int val, int target)
{
int sum = 0;
for(int i = 0; i < arrSize; i++) {
sum += arr[i] > val ? val : arr[i];
}
return abs(sum - target);
}
int findBestValue(int* arr, int arrSize, int target){
int max = INT_MIN;
int min = INT_MAX;
int avg = target / arrSize;
for(int i = 0; i < arrSize; i++) {
int val = arr[i];
max = val > max ? val : max;
min = val < min ? val : min;
}
//printf("max %d min %d avg %d\n", max, min, avg);
if(avg > max) {
return max;
}
if(avg < min) {
int n1 = avg * arrSize;
int n2 = (avg + 1) * arrSize;
return abs(n1 - target) < abs(n2 - target) ? avg : avg + 1;
}
int l = min;
int r = max;
int mid, sMid;
int lVal, rVal;
//int rSum;
int cnt = 0;
while(l <= r && cnt++ < 200) {
mid = l + (r - l) / 3;
sMid = r - (r -l) / 3;
int diff1 = GetDiff(arr, arrSize, mid, target);
int diff2 = GetDiff(arr, arrSize, sMid, target);
printf("l %d m %d sMid %d r %d diff1 %d diff2 %d target %d\n", l, mid, sMid, r, diff1, diff2, target);
if(diff1 <= diff2) {
r = sMid - 1;
//r = mid - 1;
} else {
//lSum = sum;
//l = mid + 1;
l = mid + 1;
}
}
int v1 = GetSum(arr, arrSize, l, target, 0);
int v2 = GetSum(arr, arrSize, r, target, 0);
return abs(v1 - target) < abs(v2 - target) ? l : r;
}