【发布时间】:2011-02-23 19:13:55
【问题描述】:
我有一个大约 300 项长的固定整数值数组(集合 A)。该算法的目标是根据输入 R 从该数组中选择两个符合多个标准的数字(X 和 Y)。
正式要求:
从集合 A 中选取值 X 和 Y 使得表达式 X*Y/(X+Y) 为尽可能接近 R。
仅此而已。我需要一个简单的算法来做到这一点。
其他信息:
集合 A 可以以任何方式排序或存储,最终将被硬编码。此外,通过一点数学,可以证明给定 X 的最佳 Y 是 Set A 中最接近的值表达式 X*R/(XR)。此外,X 和 Y 将始终大于 R
由此,我得到了一个可以正常工作的简单迭代算法:
int minX = 100000000;
int minY = 100000000;
foreach X in A
if(X<=R)
continue;
else
Y=X*R/(X-R)
Y=FindNearestIn(A, Y);//do search to find closest useable Y value in A
if( X*Y/(X+Y) < minX*minY/(minX+minY) )
then
minX = X;
minY = Y;
end
end
end
我正在寻找一种比这种蛮力方法更优雅的方法。有什么建议吗?
【问题讨论】:
-
你为什么称之为蛮力?蛮力将为所有
X尝试所有Y。你所拥有的是一个线性算法,它是最优的。好吧,也许你实际上可以进行二分搜索...... -
算法不是线性的——示例代码只计算最优的Y值,而不在集合A中搜索与计算值最接近的值。使用二进制搜索添加此搜索使算法在 O(n*log(n)) 中运行。
-
这听起来像是从一组可用电阻中找到两个电阻,以尽可能接近地匹配并联电路中的所需电阻。
-
@Daniel 实际上就是这样,我只是想将它简化为一个算法问题,以使其特定于编程。目标是找到一对接近所需电阻的并联电阻
-
另一个有趣的问题是寻找电阻的最佳组合,而不是将组合限制为对,但允许任意基数。在这种情况下,如果 1/R1、1/R2、...1/RN(其中 R1...RN 是可用电阻)的(排序)值正在超增(en.wikipedia.org/wiki/Superincreasing_sequence),那么这个问题是微不足道的:这正是收银员会做的(假设无限硬币/纸币)给你一个指定的金额。这正是货币细分正在超级增长的原因! 1,2,5,10,20,50 等(而不是例如 1,2,3,5,8,12 等)
标签: algorithm search performance