I'm tempted to do this backwards, which I'm not sure is allowed (see my comment.)
So instead of eliminating values one by one, let's find the smallest sub-list whose sum is within the range!
There is an issue -- the subset sum problem is np-complete, so this approach is too. (Imagine a situation in which your range is 0, and it is the same problem.)
There's a known algorithm that solves this problem in O(2N/2). I'll mock up some Python code, but in the mean time, the Wikipedia page should be helpful. Since you want to find the least list in a range, it's obviously going to need a bit of modifying.
Essentially, you split your list into two arbitrary sublists of length N/2 each (where your list has N elements.) Then generate all subsets in each list, and calculate their sums. (Here, I would store the subset and its sum in a dictionary, so you know which numbers you have left. Since you only want to find the smallest, I would also eliminate all subsets that have the same sum as a smaller one.) Sort these lists, and run through one forwards and one backwards until you find all of the sums that fit within the range. Finally, find out which contains the fewest elements, and you're good to go!
If you are allowed to make eliminations that violate the rule as long as the final list is within the range, check out this question
Edit: here's some Python. It is:
but I think as a general idea, the fastest algorithm that you're going to be able to get. I'd be interested to see a faster concept!
>>> from itertools import combinations, chain
>>>
>>> available = [-10, -5, -2, 7, 9, 15]
>>> target = (10, 18)
>>>
>>>
>>>
>>> def powerset(iterable): # from https://stackoverflow.com/questions/374626/how-can-i-find-all-the-subsets-of-a-set-with-exactly-n-elements
... xs = list(iterable)
... # note we return an iterator rather than a list
... return chain.from_iterable(combinations(xs, n) for n in range(len(xs)+1))
...
>>>
>>> def getMinList(available, target):
... middleIndex = len(available)/2
... l1 = available[:middleIndex]
... l2 = available[middleIndex:]
... dict1 = {}
... dict2 = {}
... for subset in powerset(l1): # reverse so only the smallest subsets are used.
... total = sum(subset)
... if total not in dict1:
... dict1[total] = subset
... for subset in powerset(l2):
... total = sum(subset)
... if total not in dict2:
... dict2[total] = subset
... sortedDict1 = sorted(dict1.iteritems())
... sortedDict2 = sorted(dict2.iteritems())
... resultList = ()
... minValues = middleIndex * 2
... for k1, v1 in sortedDict1:
... for k2, v2 in reversed(sortedDict2):
... sumOfSubsets = k1 + k2
... if sumOfSubsets <= target[1] and sumOfSubsets >= target[0]:
... newTuple = v1 + v2
... lenNewTuple = len(newTuple)
... if (lenNewTuple) < minValues:
... resultList = ((sumOfSubsets, newTuple))
... minValues = lenNewTuple
... return resultList
...
>>> getMinList(available, target)
(15, (15,))
>>>
>>> target = (10, 10)
>>>
>>> getMinList(available, target)
(10, (-5, 15))
>>>
>>> target = (19, 22)
>>>
>>> getMinList(available, target)
(22, (7, 15))