Вы правы, подход 1) и 3) имеют одинаковую сложность по времени, подход 2 - версия рюкзака DP (0/1), подход 1 - версия ветвления и ограничения.Вы можете улучшить первый подход, обрезав дерево с помощью любой эвристики ранца, но оптимизация должна быть строгой, например, если существующая сумма и сумма оставшихся элементов на уровне K меньше половины, пропустите ее.Этот способ подхода 1) может иметь лучшую вычислительную сложность, чем 3).
Почему у подхода 1) и 3) разное время выполнения,
[ В некоторой степени ]
Это больше связано с реализацией словарей в python.Словари изначально реализованы интерпретатором Python, любая операция над ними будет выполняться быстрее, чем все, что нужно интерпретировать в первую очередь и чаще.Кроме того, вызовы функций имеют больше накладных расходов в Python, они являются объектами.Таким образом, вызов one - это не просто увеличение стека и операция jmp / call.
[ В значительной степени ]
Еще одним аспектом, который стоит обдумать, является временная сложность третьего подхода.Для подхода 3 единственная сложность времени может быть экспоненциальной, если каждая итерация приводит к вставке столько слов, сколько имеется в словаре для текущей итерации.
cur |= { number + x for x in cur}
Приведенная выше строка должна удвоиться |cur |.
Я думаю, что это возможно для таких серий, как,
s = {k, K 2 , K 3 , ..., k n , (> K n + 1 )}
(где K - простое число> 2), чтобы датьнаихудшее время порядка 2 n для подхода 3. Еще не уверен, какова средняя ожидаемая сложность времени.