2015-04-08 46 views
0

总笔数我有一个iOS应用程序的逻辑问题,但我不想用蛮力解决它。从一套(逻辑)

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

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

我怎样才能得到一个子集,从它与这3个条件:

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

在此先感谢!

+0

你看了那[SO问题](HTTP添加的元素i ://stackoverflow.com/questions/9656789/find-2-numbers-in-an-unsorted-array-equal-to-a-given-sum)? – Azat

+0

以及http:// stackoverflow。COM /问题/ 2070359 /找到三个元素合的阵列,其森,是上最近到一个赋予号码 – Paulw11

+0

是啊,这两个相关的问题不适合这一个,因为(1)号项目在这里是无限的。 (2)如果存在多种解决方案,则不要求随机选择。 – amit

回答

3

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

然而,如果你正在处理,只有相对较低的整数 - 有使用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) 

,并产生置换的时候,你做同样的逻辑,但你决定在概率D(x-arr[i],i-1)/D(x,i)

+0

艾米特嗨,非常感谢您的帮助,您是否知道是否有办法将解决方案仅限于一定的数值​​?例如,假设总是会有一个答案,获得只与X的溶液值 – mtet88

+0

@ mtet88是,添加一个尺寸与使用的值的数量,并且修改recursivr公式'd(X,I,J)= d( (x,i-1,j)',并相应地改变停止子句,所以只有'D(0,i,0)=真'。用于计数子集数量的类似解决方案。 – amit

+0

我真的很抱歉被这个烦人,我完全失去了......用这个,我可以用这个逻辑创建新的矩阵(在这种情况下的立方体):D(x,i,j)= 0 x <0 || Ĵ<0 d(0,I,0)= 1 d(X,0,J)= 0 X!= 0 && J 1 = 0 d(X,I,J)= d(X-ARR [ i],i-1,j-1)或D(x,i-1,j),但接下来呢?实际得到解决方案的方法就完全改变了 – mtet88