代码之家  ›  专栏  ›  技术社区  ›  CodeFusionMobile

从和目标值最接近的数组中选取值的算法?

  •  2
  • CodeFusionMobile  · 技术社区  · 14 年前

    我有一系列的 几乎 排序值有28个元素长。我需要找到一组值,这些值与算法提供的目标值求和(或者如果找不到精确的和,则取最接近的和) 目标值)。

    我目前有一个简单的算法,可以完成这项工作,但它并不总是找到最佳匹配。它在理想的情况下使用一组特定的值,但我需要一个更健壮和准确的解决方案,可以处理更广泛的数据集。

    这是我目前的算法供参考。它从可用的最高值开始迭代。如果当前值小于目标和,则将该值与输出相加,然后从目标和中减去。重复此操作,直到达到总和或值用完为止。它测量一个几乎升序的排序列表。

    //valuesOut will hold a bitmask of the values to be used (LSB representing array index 0, next bit index 1, etc)
    
    void pickValues(long setTo, long* valuesOut)
    {
        signed char i = 27;//last index in array
        long mask = 0x00000001;
    
        (*valuesOut) = 0x00000000;
        mask = mask<< i;//shift to ith bit
        while(i>=0 && setTo > 0)//while more values needed and available
        {
            if(VALUES_ARRAY[i] <= setTo)
            {
                (*valuesOut)|= mask;//set ith bit
                setTo = setTo - VALUES_ARRAY[i]._dword; //remove from remaining         }
            //decrement and iterate
            mask = mask >> 1;
            i--;
        }
    }
    

    更多参数:

    • 值的数组是 几乎是升序排序,但这不能强制执行,所以假设没有排序。实际上,也可能有重复的值。

    • 最低的 总和。

    3 回复  |  直到 14 年前
        1
  •  7
  •   compie    14 年前
        2
  •  6
  •   IVlad    14 年前

    正如其他人所指出的,这与子集和问题的优化版本是相同的,它是NP完全的。

    例如,给定一个e>0,有一个多项式时间算法,它使用O((n*logt)/e)空间,(t是目标和,n是数组的大小),它给出一个子集,使得和z不小于最优值的1/(1+e)倍。

    i、 e如果最大的子集和是y,那么算法会找到一个子集和z,使得

    z <= y <= (1+e)z
    

    并使用空间O((n*logt)/e)。

    这样的算法可以在这里找到: http://www.cs.dartmouth.edu/~ac/Teach/CS105-Winter05/Notes/nanda-scribe-3.pdf

    希望这有帮助。

        3
  •  1
  •   Nikita Rybak    14 年前

    如果值相当小,则是一个简单的动态规划(DP)。时间复杂度为O(n*target),内存需求为O(target)。如果你满意的话,网上有很多DP教程。例如,这里讨论的第一个问题(与couns)与您的非常相似(除了它们允许多次使用每个数字):
    http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=dynProg

    更新