对于iOS应用程序,我有一个逻辑问题,但我不想使用蛮力解决。
我有一组整数,值不是唯一的:
[3,4,1,7,1,2,5,6,3,4........]
如何通过以下3种条件从中获取子集:
提前致谢!
这是子集和问题,它是一个已知的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)-您执行以下操作(在矩阵已填满之后):
D(SUM,n)
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随机选择采取哪种行动方式。
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
聚苯乙烯
上面给出了随机选择,但是排列的分布并不均匀。 为了实现均匀分布,您需要 计算 可能的选择数量以构建每个数字。 公式将是:
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)
i
D(x-arr[i],i-1) / D(x,i)