我已经搜索并阅读了有关此问题的算法,但它们在这种情况下似乎不适用,或者说不够清楚。
我有{{1>} 无符号值,我试图找到 sum最接近指定值N的元素
List的大小可变,平均为500个元素。 此解决方案的性能不是优先级。
如果找不到解决方案,已实施的方法应返回单一解决方案或空列表。
现有多个,选择一个元素较少的人。
List<decimal>
答案 0 :(得分:2)
首先,添加这个方便的组合扩展名:(credits to this answer)
public static class EnumerableExtensions
{
public static IEnumerable<IEnumerable<T>> Combinations<T>(this IEnumerable<T> elements, int k)
{
return k == 0 ? new[] { new T[0] } :
elements.SelectMany((e, i) =>
elements.Skip(i + 1).Combinations(k - 1).Select(c => (new[] { e }).Concat(c)));
}
}
然后:
private IEnumerable<decimal> ClosestSum(decimal[] elements, decimal n)
{
var target = Enumerable.Range(1, elements.Length)
.SelectMany(p => elements.Combinations(p))
.OrderBy(p => Math.Abs((decimal)p.Sum() - n))
.ThenBy(p => p.Count())
.FirstOrDefault();
return target ?? new decimal[] { };
}
答案 1 :(得分:1)
这可以通过dynamic programming方法相对于输入按时间线性求解。
private class Solution
{
public int StartIndex;
public int EndIndex;
public decimal Sum;
public int Length
{
get { return EndIndex - StartIndex + 1; }
}
}
static List<decimal> Solve(List<decimal> elements, decimal target)
{
Solution bestSolution = new Solution { StartIndex = 0, EndIndex = -1, Sum = 0 };
decimal bestError = Math.Abs(target);
Solution currentSolution = new Solution { StartIndex = 0, Sum = 0 };
for (int i = 0; i < elements.Count; i++)
{
currentSolution.EndIndex = i;
currentSolution.Sum += elements[i];
while (elements[currentSolution.StartIndex] <= currentSolution.Sum - target)
{
currentSolution.Sum -= elements[currentSolution.StartIndex];
++currentSolution.StartIndex;
}
decimal currentError = Math.Abs(currentSolution.Sum - target);
if (currentError < bestError || currentError == bestError && currentSolution.Length < bestSolution.Length )
{
bestError = currentError;
bestSolution.Sum = currentSolution.Sum;
bestSolution.StartIndex = currentSolution.StartIndex;
bestSolution.EndIndex = currentSolution.EndIndex;
}
}
return elements.GetRange(bestSolution.StartIndex, bestSolution.Length);
}
答案 2 :(得分:1)
我用一种老式的方式输入,但效果很好!
for i in range(len(longlist)):
longlist.replace(longlist[i],shortlist[i])