leetcode1300转变数组后最接近目标值的数组和

leetcode 1300 Sum of Mutated Array Closest to Target

Posted by BY on June 14, 2020

前言

又是好久没有更新了

正文

问题来源

本问题来自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

分析:

首先求均值和将slice进行从小到大排序,求得均值之后将小于均值的总和进行记录,然后就会得到剩余的 target - ls_t 的值 然后我们可以求得剩余的平均值为多少,由 avg = (target-ls_t)/(l - i-1)更新。当前值大于剩余均值,则当前与后续的所有值都等于剩余均值(或者剩余均值加1)。

func findBestValue(arr []int, target int) int {
    l := len(arr)
    avg := target / l 
    sort.Ints(arr)

    //abt_avg := int(math.Round(float64(target)/float64(l))) 可以替换成
    abt_avg := avg
    if target - avg*l > l/2 {
        abt_avg ++
    }
    //arr自小到大,第一个都大于abt_avg(均值),直接就可以返回均值
    if abt_avg <= arr[0] {
        return abt_avg
    }
    //最后一个都小于均值,则返回arr最后一个值
    if arr[l-1] <= abt_avg {
        return arr[l-1]
    }
    // mean total less of average 
    // 小于平均值的数的总和
    ls_t := 0
    i := 0
    for ; i < l; i++ {
        // 当前值大于剩余均值,后面的值都会大于剩余均值
        // 让当前以后的值都等于剩余均值或者剩余均值+1即可
        if arr[i] > avg {
            // 比较(l-i)*avg与(l-i)*(avg+1)两者谁更接近target-ls_t,因为题目要求两者相等时取更小的值
            if int(math.Abs(float64(target-ls_t - (l-i)*avg))) <= int(math.Abs(float64(target-ls_t-(l-i)*(avg+1)))) {
                return avg
            }
            return avg+1
        } else if i != l - 1 { // 小于等于剩余均值,但是避免出现除0的情况
            // 记录小于均值的总和
            ls_t += arr[i]
            // 更新剩余的均值
            avg = (target-ls_t)/(l - i-1)
        }
    }
    return arr[l-1]
}

做完之后看有没有好的解法,发现有人跟我的想法一样,少了一些判断

int cmp(const void* c1, const void* c2) {
    return *(int*)c1 - *(int*)c2;
}

int findBestValue(int* arr, int arrSize, int target){
    if (arr == NULL) {
        return 0;
    }
    // 注意qsort的使用方法
    qsort(arr, arrSize, sizeof(int), cmp);
    int sum = 0;
    for (int i = 0; i < arrSize; i++) {
        int x = (target - sum) / (arrSize - i);
        if (x < arr[i]) {
            double t = ((double)(target - sum))/(arrSize - i);
            if (t - x > 0.5) {
                return x + 1;
            } else {
                return x;
            }
        }
        sum += arr[i];
    }
    return arr[arrSize - 1];
}

要注意C语言中qsort的使用方法。

总结:

勤思考。

结语

不管怎么样好好加油。