找出两个具有最小差异的不相交的后序(> n)

时间:2015-02-08 11:14:15

标签: algorithm dynamic-programming combinatorics subsequence

给出一组正数,你需要找到两个不相交的子序列,其最小差值小于或等于n。这些子序列可能是也可能不是连续的

For Example 

if array = [10,12,101,105,1000] and n = 10
Ans = [10,105] & [12,101]

If minimum difference > n then there is no solution.

Ex- array = [100, 150, 125] and n = 7

我认为可以使用DP完成此操作,但我无法获得重复。

1 个答案:

答案 0 :(得分:0)

如果所有元素的总和不是太大(在数百万之内),那么你可以做一个类似于背包问题的解决方案。您的DP状态是两组之间的差异,对于您迭代目前所知的所有差异的每个元素,并更新它们。由于差异不能超过所有元素的总和,因此复杂性最终为O(n * s),其中n是元素的数量,s是它们的总和。你需要某种逻辑来恢复答案。例如,如果所有元素都是非负数,则可以只存储先前的差异。这是一个示例python代码(我稍微修改了您的示例案例,因为对于您的情况,它找到了一个无趣的答案[10], [12]

a = [5, 20, 30, 1000]
n = 7

states = {(0, False, False): None} # state is sum, hasPositive, hasNegative => prevsum, prevHasP, prevHasN
for el in a:
    newStates = {}

    for k, v in states.items():
        newStates[k] = v

    for v, hasP, hasN in states:
        if (v + el, True, hasN) not in newStates:
            newStates[(v + el, True, hasN)] = (v, hasP, hasN)
        if (v - el, hasP, True) not in newStates:
            newStates[(v - el, hasP, True)] = (v, hasP, hasN)

    states = newStates

best = None
for key, hasP, hasN in states.keys():
    if key >= -n and key <= n and hasP and hasN and (best == None or abs(best[0]) > abs(key)):
        best = (key, hasP, hasN)

if best is None: print "Impossible"
else:
    ans1 = []
    ans2 = []
    while best[1] or best[2]: # while hasPositive or hasNegative
        prev = states[best]

        delta = best[0] - prev[0]
        if delta > 0:
            ans1.append(delta)
        else:
            ans2.append(- delta)

        best = prev

    print ans1
    print ans2

正如我前面提到的,只有当你的所有元素都是非负数时它才会起作用,但是如果元素可以是负数,那么很容易调整恢复答案的代码也可以工作。