【问题标题】:Find the best approximation of a subset for a value找到一个值的子集的最佳近似值
【发布时间】:2020-09-22 14:46:43
【问题描述】:

我想获得一种算法,它可以为我提供基于子集的值的最佳近似值。

这是一个例子:

N = 45

subset = [25,10,65,9,8]

output: [25,10,9]

重要的一点是算法必须给出最好的近似值(不管最终结果中元素的数量)。结果必须提供给出最接近的确切值的关联(但不能超过初始值)。

您知道可以以最少的时间成本做到这一点的算法吗?

非常感谢您的帮助。

【问题讨论】:

  • 你试过什么?所有数字都是正数吗?
  • 是的,都是正面的
  • 你的意思是,总数最接近但不大于给定数字的子集?如果有很多可能的子集呢?
  • 我的意思是,如果数字是 45,则找到的关联不能大于 45。如果有许多可能的子集可以提供最佳近似值,我们只取其中一个。
  • 你的意思是输出列表中值的总和必须尽可能接近N吗?

标签: python algorithm nearest-neighbor


【解决方案1】:

你不能在多项式时间内这样做(除非 P=NP)

找出是否存在一个总和正好为 N 的子集显然比找到总和最接近 N 的子集要容易,而前一个问题称为subset-sum,已知是 NP 完全的。

但是,伪多项式时间是可能的。实际上,如果我们将subset 中的值作为转换为背包的权重值,则您的问题与0/1 knapsack optimization problem 完全相同。这个 0/1 背包问题有一个在 O(nW) 中运行的动态规划解决方案,其中 nsubset 中的项目数,W 是目标,即代码中的 N

【讨论】:

    【解决方案2】:

    以下代码适用于短名单。但是,对于较长的列表,性能会显着降低:

    import itertools
    def closest(my_list, my_number):
        l=[]
        for i in range(1,len(my_list)+1):
            for k in itertools.combinations(my_list, i):
                l.append([k, sum(k)])
        l=[i for i in l if i[1]<=my_number]
        l.sort(key=lambda x:x[1])
        return l[-1]
    print(closest(subset, 45)[0], closest(subset, 45)[1])
    

    输出:

    (25, 10, 9) 44
    

    【讨论】:

    • 谢谢。我试图理解你的做法。什么是“itertools.combinations”?
    • 好的,我明白了!但是在 "for k in itertools.combinations(my_list, i):" 行中应该是 "i+1" 不?
    • 这是一个返回列表所有组合的函数。在这里查看:stackoverflow.com/questions/17053070/making-combinations-python
    • 是的,你是对的,我更改了代码,以便它将循环 1 到 len(my_list)(包括)
    • 好的,谢谢!我尝试找出组合的复杂度以获得该算法的总复杂度。
    猜你喜欢
    • 2021-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多