Вот O (n) ожидаемое время решения проблемы.Это похоже на идею Морона, но мы не выкидываем работу, которую выполнял наш алгоритм выбора на каждом шаге, и мы начинаем пробовать элемент потенциально посередине, а не использовать повторяющийся метод удвоения.
В качестве альтернативы, это просто быстрый выбор с небольшим дополнительным бухгалтерским учетом на оставшуюся сумму.
Во-первых, ясно, что если бы у вас были элементы в отсортированном порядке, вы могли бы сначала выбрать самые большие элементы, пока не превысите желаемую сумму.Наше решение будет таким, за исключением того, что мы будем стараться изо всех сил, чтобы не находить информацию о заказе, потому что сортировка медленная.
Вы хотите иметь возможность определить, является ли данное значениеотрезать.Если мы включим это значение и все, что больше его, мы встретим или превысим S, но когда мы удаляем его, то мы ниже S, тогда мы золотые.
Вот код psuedo, я не сделалПротестируйте его для крайних случаев, но это дает представление.
def Solve(arr, s):
# We could get rid of worse case O(n^2) behavior that basically never happens
# by selecting the median here deterministically, but in practice, the constant
# factor on the algorithm will be much worse.
p = random_element(arr)
left_arr, right_arr = partition(arr, p)
# assume p is in neither left_arr nor right_arr
right_sum = sum(right_arr)
if right_sum + p >= s:
if right_sum < s:
# solved it, p forms the cut off
return len(right_arr) + 1
# took too much, at least we eliminated left_arr and p
return Solve(right_arr, s)
else:
# didn't take enough yet, include all elements from and eliminate right_arr and p
return len(right_arr) + 1 + Solve(left_arr, s - right_sum - p)