I was trying a basic way to solve a subset sum problem faster and I came up with this
The naive way is the oldSS function, which tests all 2^n combinations. But then I noticed that, before checking each case, calculate the min and max value possible for the current scenario, and if the target lies in side that range, and it could potentially be a solution there, so only then execute the scenario. This is the newSS function. I was testing the times, and it gave me this
9.91289400371 0.00154754789233 I could further improve the newSS time by caching the getMinMax values into a global variable. However for the naive approach, the time can be improved to 2^(n/2) using a clever hack that cuts the initial list by 2 and then doing the naive approach on each and then comparing the two generated lists.
But compared to the 2^(n/2) running time, does anyone know how well the newSS function does?
Thanks
import timeit from random import randint def oldSS(lst, acc, target): if lst: return oldSS(lst[1:], acc+lst[0], target) or oldSS(lst[1:], acc, target) return acc==target def randomList(): l = [] for i in range(20): l.append(randint(0,1000)) return l def getMinMax(lst): mi = 0 mx = 0 for i in lst: if i < 0: mi += i elif i > 0: mx += i return (mi, mx) def newSS(lst, acc, target): if lst: a = False b = False mimx = getMinMax(lst[1:]) nmi = acc+lst[0] + mimx[0] nmx = acc+lst[0] + mimx[1] if target >= nmi and target <= nmx: a = newSS(lst[1:], acc+lst[0], target) nmi = acc + mimx[0] nmx = acc + mimx[1] if target >= nmi and target <= nmx: b = newSS(lst[1:], acc, target) return a or b return acc==target if __name__ == '__main__': print timeit.timeit('oldSS(randomList(), 0, 60)', number=10, setup="from __main__ import oldSS,randomList") print timeit.timeit('newSS(randomList(), 0, 60)', number=10, setup="from __main__ import newSS,getMinMax,randomList")