一尘不染

一组总和(逻辑)

algorithm

对于iOS应用程序,我有一个逻辑问题,但我不想使用蛮力解决。

我有一组整数,值不是唯一的:

[3,4,1,7,1,2,5,6,3,4........]

如何通过以下3种条件从中获取子集:

  • 我只能选择定义数量的值。
  • 选取的元素之和等于一个值。
  • 选择必须是随机的,因此,如果该值有多个解决方案,则它不会总是返回相同的值。

提前致谢!


阅读 192

收藏
2020-07-28

共1个答案

一尘不染

这是子集和问题,它是一个已知的NP完全问题,因此没有已知的有效(多项式)解决方案。

但是
,如果只处理相对较小的整数,则可以使用动态编程来创建
伪多项式 时间解决方案。

这个想法是建立一个遵循下一个递归公式的自下而上的矩阵:

D(x,i) = false   x<0
D(0,i) = true
D(x,0) = false   x != 0
D(x,i) = D(x,i-1) OR D(x-arr[i],i-1)

想法是模仿详尽的搜索-在每个点上,您都会“猜测”是否选择了元素。

要获得实际的子集,您需要追溯矩阵。您从进行迭代D(SUM,n)(假设值是true)-您执行以下操作(在矩阵已填满之后):

if D(x-arr[i-1],i-1) == true:
    add arr[i] to the set
    modify x <- x - arr[i-1]
    modify i <- i-1
else // that means D(x,i-1) must be true
    just modify i <- i-1

要同时获得一个随机子集,如果两者都D(x-arr[i-1],i-1) == true与AND D(x,i-1) == true随机选择采取哪种行动方式。

Python代码(如果您不知道python将其读取为伪代码,则非常容易遵循)。

arr = [1,2,4,5]
n = len(arr)
SUM = 6
#pre processing:
D = [[True] * (n+1)]
for x in range(1,SUM+1):
    D.append([False]*(n+1))
#DP solution to populate D:
for x in range(1,SUM+1):
    for i in range(1,n+1):
        D[x][i] = D[x][i-1]
        if x >= arr[i-1]:
            D[x][i] = D[x][i] or D[x-arr[i-1]][i-1]
print D

#get a random solution:

if D[SUM][n] == False:
    print 'no solution'
else:
    sol = []
    x = SUM
    i = n
    while x != 0:
        possibleVals = []
        if D[x][i-1] == True:
            possibleVals.append(x)
        if x >= arr[i-1] and D[x-arr[i-1]][i-1] == True:
            possibleVals.append(x-arr[i-1])
        #by here possibleVals contains 1/2 solutions, depending on how many choices we have.
        #chose randomly one of them
        from random import randint
        r = possibleVals[randint(0,len(possibleVals)-1)]
        #if decided to add element:
        if r != x:
            sol.append(x-r)
        #modify i and x accordingly
        x = r
        i = i-1
    print sol

聚苯乙烯

上面给出了随机选择,但是排列的分布并不均匀。
为了实现均匀分布,您需要 计算 可能的选择数量以构建每个数字。
公式将是:

D(x,i) = 0 x<0
D(0,i) = 1
D(x,0) = 0   x != 0
D(x,i) = D(x,i-1) + D(x-arr[i],i-1)

在生成排列时,您执行相同的逻辑,但是您决定将元素添加到i概率中D(x-arr[i],i-1) / D(x,i)

2020-07-28