给定一个N个非负整数的数组A,找到一个整数k,这样每个元素与k的差值之和最小。
即求和(abs(A [i] - k)),1< = i< = N,或简称为
| A [1] - k | + | A [2] - k | + | A [3] - k | + ... + | A [N] - k |
我的方法:
low = minimumValueInArray(A);
high= maximumValueInArray(A);
ans = Infinite;
for (k = low; k <= high; k++) {
temp = 0;
for (i = 1; i <= N; i++) {
temp += abs(A[i] - K);
}
ans = min(ans, temp);
}
return ans;
这只是蛮力的方法,试图解决K的所有价值。我们可以优化它 这样做的更聪明的方法是什么?
参考:这是我背后的逻辑 Codejam Round 1B problem
答案 0 :(得分:3)
我基本上得到了中位数。要最小化成本函数,请采用导数。
要查找成本函数的最小值,请找出导数为零的位置。成本函数在任何地方都不是连续可微的,但它是分段可微的。设S = A和si的排序数是第i个最大数。
将会有楼层(m / 2)ai小于中位数且楼层(m / 2)ai大于中位数。选择x =中位数,给出-m / 2 + 0 + m / 2 = 0。
对于si和s之间的值,导数将为零(i + 1); i = m / 2。然后可以选择任何数字k,以便
简单的例子 1 2 4 50
选择2:1 + 0 + 2 + 48 = 51
选择4:3 + 2 + 0 + 46 = 51
选择3:2 + 1 + 1 + 47 = 51
所以任意选择s(m / 2)
对于更好的算法,O(NlogN)您可以对数字进行排序,然后根据需要从上面选择(m + 1)/ 2或m / 2,或者您可以使用可以计算答案的kth largest element在O(N)。
答案 1 :(得分:1)
给定一组数字A_1,...,A_N,已知(参见例如http://homepages.gac.edu/~holte/courses/mcs256/problems/median.pdf)中位数最小化绝对偏差之和。
由于你有一个整数数组,所以:
(a)N为奇数,中位数为整数m,您将k设为。
(b)N是偶数,中位数是两个整数a和b的平均值。在这种情况下,事实证明a和b之间的所有数字都使绝对偏差的总和最小化。所以你可以选择k作为a,b或中间的任何整数(如果有的话)。
例如,如果数字是1,3,4,6,9 - 中位数是4,则将k设置为。 如果数字是4,7,12,15,则中位数是(7 + 12)/ 2,你可以将k设置为7到12之间的任何数字。例如,k = 7给出总偏差(7-4)+(7 -7)+(12-7)+(15-7)= 16且k = 12给出总偏差(12-4)+(12-7)+(12-12)+(15-12)= 16。
答案 2 :(得分:-1)
您可以以数字线上的点的形式表示数组中的所有值。
例如,数字行上的点可能如下所示:
_____________________ 4 ___________ 7 _______________________ 12 ___________ 15
所以根据问题定义,我们可以说数字线上与所有点等距的点应该给出正确的答案。
所以你要做的就是找到所有数字的平均值。将答案作为更接近平均值的整数返回。例如,对于2.66返回3,对于2.2返回2,对于2.5返回2或3中的任何一个。
运行时间:O(N)
来计算数字的平均值。