leetcode算法练习:转变数组后最接近目标值的数组和

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值