一组总和(逻辑)

时间:2015-04-08 10:46:36

标签: ios algorithm optimization logic brute-force

我对iOS应用程序存在逻辑问题,但我不想使用暴力解决它。

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

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

如何通过以下三个条件从中获取子集:

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

提前致谢!

1 个答案:

答案 0 :(得分:3)

这是subset sum proble m,它是已知的NP-Complete问题,因此没有已知的有效(多项式)解决方案。

然而,如果你只处理相对较低的整数 - 使用Dynamic Programming有一个伪多项式时间解决方案。

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

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) == trueD(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

<强> P.S。

上面给出了随机选择,但没有统一分布排列。
要实现统一分布,您需要计算构建每个数字的可能选择的数量。
公式将是:

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)