我对iOS应用程序存在逻辑问题,但我不想使用暴力解决它。
我有一组整数,值不是唯一的:
[3,4,1,7,1,2,5,6,3,4........]
如何通过以下三个条件从中获取子集:
提前致谢!
答案 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) == true
和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
<强> 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)