给你一个整数数组 arr 和一个目标值 target ,请你返回一个整数 value ,使得将数组中所有大于 value 的值变成 value 后,数组的和最接近 target(最接近表示两者之差的绝对值最小)。
如果有多种使得和最接近 target 的方案,请你返回这些整数中的最小值。
请注意,答案不一定是 arr 中的数字。
题解:
1.一个整数数组 arr 和一个目标值 target
2.将数组中所有大于 value 的值变成 value
3.数组的和与target之差的绝对值最小
4.如果有多个value使数组和接近target,返回整数最小的
示例 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
提示:
1 <= arr.length <= 10^4
1 <= arr[i], target <= 10^5
解题思路:
-
先对数组从小到大进行排序
-
从前向后遍历每一个元素,试探当以arr[i]为value时,数组和距离target的距离
-
当以arr[i]为value时,数组和为前i个元素之和+arr[i]*(length-i),因为arr[i]之后的元素都更新为arr[i]的值
-
如此遍历下去如果数组和大于target,则可以停止继续向下试探
-
其次是如果有多种方案,保留值小的用找到的当前value大1的比较
-
如果当前值value更接近target或当前值value和value加1的值距离target相等,返回value,因为value是更小的方案;否则返回value+1
C/C++题解:
class Solution {
public:
int findBestValue(vector<int>& arr, int target) {
sort(arr.begin(), arr.end());//从小到大排序
int frontSum = 0;//前i个和
int i, length = arr.size();
for (i = 0; i < length; i ++) {
//以当前arr[i]为value,求和
int allSum = frontSum + arr[i] * (length - i);
if (allSum > target) break;//当计算到大于target不需要往下计算了
frontSum += arr[i];//前i个和
}//如果遍历到最后一个数仍小于target,则value为最后一个数
if (i == length) return arr[length];
//如果在中间某个值为value大于target,后部分和为remain
int remain = target - frontSum;
int l = remain / (length - i);//除以剩余个数为value
int r = l + 1;//用比value大1的数试探是不是最小的方案
if (remain - l * (length - i) <= r * (length - i) - remain)
return l;//如果用r大,返回小的值l
else//否则用r做value的数组和更接近target
return r;}};
Debug结果:
Java题解:
class Solution {
public int findBestValue(int[] arr, int target) {
Arrays.sort(arr);//从小到大排序
int frontSum = 0;//前i个和
int i, length = arr.length;
for (i = 0; i < length; i ++) {
//以当前arr[i]为value,求和
int allSum = frontSum + arr[i] * (length - i);
if (allSum > target) break;//当计算到大于target不需要往下计算了
frontSum += arr[i];//前i个和
}//如果遍历到最后一个数仍小于target,则value为最后一个数
if (i == length) return arr[length];
//如果在中间某个值为value大于target,后部分和为remain
int remain = target - frontSum;
int l = remain / (length - i);//除以剩余个数为value
int r = l + 1;//用比value大1的数试探是不是最小的方案
if (remain - l * (length - i) <= r * (length - i) - remain)
return l;//如果用r大,返回小的值l
else//否则用r做value的数组和更接近target
return r;}}
Debug结果:
Python题解:
class Solution(object):
def findBestValue(self, arr, target):
""":type arr: List[int]:type target: int:rtype: int"""
arr.sort() #从小到大排序
frontSum = 0 #前i个和
i, length = 0, len(arr)
for i in range(length):
#以当前arr[i]为value,求和
allSum = frontSum + arr[i] * (length - i)
if allSum > target: break #当计算到大于target不需要往下计算了
frontSum += arr[i] #前i个和
#如果遍历到最后一个数仍小于target,则value为最后一个数
if i == length: return arr[length]
#如果在中间某个值为value大于target,后部分和为remain
remain = target - frontSum
l = remain / (length - i) #除以剩余个数为value
r = l + 1 #用比value大1的数试探是不是最小的方案
if remain - l * (length - i) <= r * (length - i) - remain:
return l #如果用r大,返回小的值l
else: #否则用r做value的数组和更接近target
return r
Debug结果:
更多题解移步公众号免费获取