我有一个值列表。可以说他们是{1,2,3,4,5}
我想找到总和最接近给定值的组合
例如,如果我输入8,则该函数可以返回 {3,5}或{1,3,4}。这两个都是正确的,而我只会选择索引最少3 + 5的那个
如果没有确切的值(例如9.45),它将返回该值 不超过阈值{4,5}
我不确定我从哪里开始。我认为使用linq查询是可能的...
答案 0 :(得分:0)
static IEnumerable<int> GetClosestValues(IReadOnlyList<int> c, int t)
{
var s=0m;
return c.Select((x, i) => i).OrderByDescending(i => c[i]).Where(i => (s += c[i]) <= t).OrderBy(i => i);
}
似乎可以正常使用...
答案 1 :(得分:0)
关键是要找到集合的所有排列,然后通过LINQ过滤(小于或等于阈值)和顺序(按与阈值的距离,然后按集合的大小):
var source = Enumerable.Range(1, 5).Select(x => (double)x).ToArray();
var permutations = Enumerable.Range(1, source.Length)
.SelectMany(x => Utils.GetOrderedPermutations(source, x))
.Dump();
var threshold = 9.45;
var result = permutations
.Select(x => x.ToArray())
.Select(x => new { Set = x, Sum = x.Sum() })
.Where(x => x.Sum <= threshold)
.OrderBy(x => threshold - x.Sum)
.ThenBy(x => x.Set.Length)
.FirstOrDefault()
.Dump();
GetOrderedPermutations
来自此answer:
public class Utils
{
public static IEnumerable<T> Yield<T>(T value)
{
yield return value;
}
public static IEnumerable<IEnumerable<T>> GetOrderedPermutations<T>(IEnumerable<T> source, int k)
{
if (k == 0) return new[] { Enumerable.Empty<T>() };
int length = source.Count();
if (k == length) return new[] { source };
if (k > length) return Enumerable.Empty<IEnumerable<T>>();
return GetOrderedHelper<T>(source, k, length);
}
private static IEnumerable<IEnumerable<T>> GetOrderedHelper<T>(IEnumerable<T> source, int k, int length)
{
if (k == 0)
{
yield return Enumerable.Empty<T>();
yield break;
}
int i = 0;
foreach (var item in source)
{
if (i + k > length) yield break;
var permutations = GetOrderedHelper<T>(source.Skip(i + 1), k - 1, length - i);
i++;
foreach (var subPerm in permutations)
{
yield return Yield(item).Concat(subPerm);
}
}
}
}