问题:
给出一个数组,和一个目标值target
求一个数值value,将数组中所有>value的数换成value后,使得数组和最接近target
Example 1: Input: arr = [4,9,3], target = 10 Output: 3 Explanation: When using 3 arr converts to [3, 3, 3] which sums 9 and that's the optimal answer. Example 2: Input: arr = [2,3,5], target = 10 Output: 5 Example 3: Input: arr = [60864,25176,27249,21296,20204], target = 56803 Output: 11361 Constraints: 1 <= arr.length <= 10^4 1 <= arr[i], target <= 10^5
解法:
思考边界情况:
如数组[3,4,9]
只能换>value的数:
最小:(全部arr[i]>value)将所有元素都换成value(value<3):[value, value, value]->target=3*value (有可能为[1,1,1]...)
最大:(全部arr[i]<value)所有元素都换不成value,只能保持原样:[3,4,9]->target>3+4+9=16 (value最大取max(arr[i])=9)
遍历排序后的数组,尝试value从小(target/n)取到大(max(arr[i])),对比target的值。
遍历数组:
如果value取arr[0]之前,target<=arr[0]*3的话,直接返回value=round((target-0.0001)/3) round:四舍五入函数
如果 target>arr[0]*3:那么,增大现在的比较对象(3个arr[0]->1个arr[0]+2个arr[1])(因为arr[0]<arr[1])
即:target-=arr[0],然后比较 减去arr[0]后的target 和 arr[1]*2,如果 target<=arr[1]*2 ,同上返回value=round((target-0.0001)/2)
⚠️ 注意:由于如果有两个整数到target的绝对距离相同(一正一负两个方向趋近),取较小的值,因此-0.0001
总结这个遍历即为:
while( i<n && target>arr[i]*(n-i) ) { target-=arr[i]; i++; } return round((target-0.0001)/(n-i));
参考代码:
1 class Solution { 2 public: 3 int findBestValue(vector<int>& arr, int target) { 4 int n=arr.size(), i=0; 5 sort(arr.begin(), arr.end()); 6 while(i<n && target>arr[i]*(n-i)){ 7 target-=arr[i]; 8 i++; 9 } 10 return (i==n)?arr[n-1]:int(round((target-0.0001)/(n-i))); 11 } 12 };