【问题标题】:Total sum from a set (logic)一组总和(逻辑)
【发布时间】:2015-04-08 10:46:36
【问题描述】:

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

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

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

如何在这 3 个条件下从中获取子集:

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

提前致谢!

【问题讨论】:

  • 你读过SO question吗?
  • 是的,这两个相关问题都不适合这个问题,因为 (1) 项目数量在这里是无限的。 (2) 如果存在多个解决方案,则 None 要求随机选择。
  • 正如 Amit 在他的回答中指出的那样,问题是 NP-Complete。不过,您并没有在问题中提到无限数量的项目 - 这意味着您无法对项目进行排序
  • 项目数量有限,但如果有多个选项,则需要随机解决方案

标签: ios algorithm optimization logic brute-force


【解决方案1】:

这是subset sum problem,它是一个已知的 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

附言

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

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)

【讨论】:

  • 嗨,Amit,非常感谢您的帮助,您知道是否有任何方法可以将解决方案限制为一定数量的值?例如,假设总会有一个答案,只得到一个 X 值的解
  • @mtet88 是的,添加一个包含所用值数量的维度,并将recursivr 公式修改为D(x,i,j) = D(x-arr[i],i-1,j-1) OR D(x,i-1,j),并相应地更改停止子句,因此只有D(0,i,0) = true。计算子集数量的类似解决方案。
  • 我真的很抱歉这么烦人,我完全迷失了......有了这个我可以用这个逻辑创建新的矩阵(在这种情况下是立方体):D(x,i, j) = 0 x
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-08
  • 2020-10-06
  • 1970-01-01
  • 1970-01-01
  • 2010-10-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多