高效算法,通过将给定数字添加到列表中所有元素或其补码的总和来查找最大结果

时间:2012-11-12 21:48:11

标签: c# java algorithm math

假设我有号码x,号码列表和最大号码y。我需要找到最大结果,我可以通过将x添加到列表中每个元素的加法或减法中来获得最大结果,使得求和不超过y且不低于0.

注意:您必须在列表中添加或减去每个元素,这意味着您不能跳过数字。

示例:

x= 3 y=10  list={2,6,1}

我可以得到:3 - 2 + 6 +1 = 8小于10且小于0
失败案例3+2+6+1= 12,即>因此无效的解决方案。
另一个失败案例 3-2-6 = -5(此处不需要在6之后检查元素,因为你的号码被拒绝了)

如何找到这个最大值?

2 个答案:

答案 0 :(得分:3)

因此,您基本上有一个列表l和一个y-x号码(如果您必须添加x,并获得y,则很容易看到它是相当于获取y-x)并且您希望在l中添加/减去每个元素并尽可能接近值y-x

请注意,问题等同于Partition Problem NP-Complete,因为如果您有一个列表l,并且值y-x == 0 - 则需要找到两个子列表l1,l2,使sum(l1) - sum(l2) == 0l1 union l2 = l正好是分区问题。

因此 - 没有已知的多项式解决方案。

我会看一下指数(例如回溯)解决方案,或pseudo polynomial DP solution for the related subset sum problem的变体。

答案 1 :(得分:0)

以下是解决方案:

    int x = 3, y = 10;
    var lst = new List<int>{ 1, 2, 3, 4 };
    int n = (int)Math.Pow(2, lst.Count);
    var lst2 = new List<List<int>>();
    for (int i = 0; i < n; i++)
    {
        var lstCopy = new int[lst.Count];
        lst.CopyTo(lstCopy);
        for (int j = 1; j <= i; j *= 2)
            if ((j & i) != 0)
                lstCopy[(int)Math.Log(j, 2)] *= -1;
        lst2.Add(lstCopy.ToList());
    }
    bool yes = lst2.Select(l=>x + l.Sum()).Any(l=>l > 0 && l < y);
    if (yes)
        Console.WriteLine(lst2.Select(l => x + l.Sum()).Where(l => l > 0 && l < y).First());

请注意,您需要检查2 ^ n个整数数组,其中n是原始数组的长度(它是您的{2,6,1}}