我获得了以下任务:
给定A(i)形式的N个整数,其中1≤i≤N,得到每个数 A(i)中的N个数等于M.要将数字A(i)转换为M,它 将花费| M-Ai |单位。找出转换所有N的最低成本 数字到M,所以你应该选择最好的M来获得最低成本。
假设:
1 <= N <= 10^5 1 <= A(i) <= 10^9
我的方法是计算所有数字的总和并找到avg = sum / n
,然后将每个数字减去avg
以获得最低费用。
但是在许多测试用例中都失败了。我怎样才能找到最佳解决方案?
答案 0 :(得分:4)
你应该取数字的中位数(如果列表长度均匀,则取两个数字中间最接近的数字),而不是均值。
平均值未能最小化的示例是:[1,2,3,4,100]。平均值是110/5 = 22,总成本是21 + 20 + 19 + 18 + 78 = 156.选择中位数(3)给出总成本:2 + 1 + 0 + 1 + 97 = 101。
中位数位于列表中两个项目之间的示例是[1,2,3,4,5,100]。这里的中位数是3.5,使用M = 3或M = 4都可以。对于M = 3,总成本为2 + 1 + 0 + 1 + 2 + 97 = 103.对于M = 4,总成本为3 + 2 + 1 + 0 + 1 + 96 = 103。
可以在Mathematics SE上找到正确的正式证明,尽管您可以通过注意如果您在一个方向上轻微推动M(但不是超过其中一个数据点)来说服您自己的结果 - 例如,让我们说它是正方向,总成本增加delta乘以M左边的点数减去delta乘以点的数量当左边和右边的点数在数量上相等时,M的权利被最小化,否则你可以以一种方式向其移动少量以减少总成本。
答案 1 :(得分:0)
我在他最后一个答案的最后一段中与@PaulHankin做了类似的观察。这让我意识到,为了找到m
,我必须迭代地消除异常值。所以我编写了一个程序,首先对输入数组(向量)A
进行排序,然后分析最小值和最大值。
这个想法是将最小值移向第二个最小值,将最大值移向第二个最大值。您始终移动最小值或最大值,具体取决于您是否具有最小值而不是最大值。如果所有数组项最终都是相同的值,那么您找到了m
:
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
int getMinCount(vector<int>& A);
int getMaxCount(vector<int>& A);
int main()
{
// Example as given by @PaulHankin
vector<int> A;
A.push_back(1);
A.push_back(2);
A.push_back(3);
A.push_back(4);
A.push_back(100);
sort(A.begin(), A.end());
int minCount = getMinCount(A);
int maxCount = getMaxCount(A);
while (minCount != A.size() && maxCount != A.size())
{
if(minCount <= maxCount)
{
for(int i = 0; i < minCount; i++)
A[i] = A[minCount];
// Recalculate the count of the minium value, because we changed the minimum.
minCount = getMinCount(A);
}
else
{
for(int i = 0; i < maxCount; i++)
A[A.size() - 1 - i] = A[A.size() - 1 - maxCount];
// Recalculate the count of the maximum value, because we changed the maximum.
maxCount = getMaxCount(A);
}
}
// Print out the one and only remaining value, which is m.
cout << A[0] << endl;
return 0;
}
int getMinCount(vector<int>& A)
{
// Count how often the minimum value exists.
int minCount = 1;
int pos = 1;
while (pos < A.size() && A[pos++] == A[0])
minCount++;
return minCount;
}
int getMaxCount(vector<int>& A)
{
// Count how often the maximum value exists.
int maxCount = 1;
int pos = A.size() - 2;
while (pos >= 0 && A[pos--] == A[A.size() - 1])
maxCount++;
return maxCount;
}
如果您考虑算法,那么您将得出结论,它实际上计算了数组A
中值的中值。作为示例输入,我采用了@PaulHankin给出的第一个示例。正如所料,代码为它提供了正确的结果(3)。
我希望我的方法可以帮助您了解如何解决此类问题,即使您不知道正确的解决方案。例如,当你参加面试时,这尤其有用。