获取总和接近给定值的项目

时间:2018-11-29 21:13:30

标签: c#

我有一个值列表。可以说他们是{1,2,3,4,5}

我想找到总和最接近给定值的组合

例如,如果我输入8,则该函数可以返回 {3,5}或{1,3,4}。这两个都是正确的,而我只会选择索引最少3 + 5的那个

如果没有确切的值(例如9.45),它将返回该值 不超过阈值{4,5}

我不确定我从哪里开始。我认为使用linq查询是可能的...

2 个答案:

答案 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);
            }
        }
    }
}