Я хочу иметь функцию, которая будет возвращать обратный список, который ей задан, используя рекурсию. Как я могу это сделать?
Как перевернуть список с помощью рекурсии в Python?
Ответы (16)
Добавьте первый элемент списка в перевернутый подсписок:
mylist = [1, 2, 3, 4, 5]
backwards = lambda l: (backwards (l[1:]) + l[:1] if l else [])
print backwards (mylist)
Немного более явно:
def rev(l):
if len(l) == 0: return []
return [l[-1]] + rev(l[:-1])
Это превращается в:
def rev(l):
if not l: return []
return [l[-1]] + rev(l[:-1])
Что превращается в:
def rev(l):
return [l[-1]] + rev(l[:-1]) if l else []
Это то же самое, что и другой ответ.
Хвостовой рекурсивный/стиль CPS (который python все равно не оптимизирует):
def rev(l, k):
if len(l) == 0: return k([])
def b(res):
return k([l[-1]] + res)
return rev(l[:-1],b)
>>> rev([1, 2, 3, 4, 5], lambda x: x)
[5, 4, 3, 2, 1]
Я знаю, что это бесполезный ответ (хотя на этот вопрос уже был дан ответ), но в любом реальном коде, пожалуйста, не делайте этого. Python не может оптимизировать хвостовые вызовы, имеет медленные вызовы функций и имеет фиксированную глубину рекурсии, поэтому есть как минимум 3 причины, по которым вместо этого следует делать это итеративно.
Хитрость заключается в том, чтобы присоединиться после рекурсии:
def backwards(l):
if not l:
return
x, y = l[0], l[1:]
return backwards(y) + [x]
Используйте стратегию «Разделяй и властвуй». Алгоритмы D&C являются рекурсивными алгоритмами. Чтобы решить эту проблему с помощью D&C, необходимо выполнить два шага:
- Разберитесь с базовым случаем. Это должен быть самый простой возможный случай.
- Разделите или уменьшите свою проблему, пока она не станет базовым случаем.
Шаг 1: Определите базовый вариант. Какой самый простой список вы можете получить? Если вы получаете список с 0 или 1 элементом, это довольно легко подвести итог.
if len(l) == 0: #base case
return []
Шаг 2: Вам нужно приближаться к пустому списку с каждым рекурсивным вызовом
recursive(l) #recursion case
Например
l = [1,2,4,6]
def recursive(l):
if len(l) == 0:
return [] # base case
else:
return [l.pop()] + recursive(l) # recusrive case
print recursive(l)
>[6,4,2,1]
Источник: Алгоритмы Grokking
Этот переворачивается на месте. (Конечно, итеративная версия была бы лучше, но она должна быть рекурсивной, не так ли?)
def reverse(l, first=0, last=-1):
if first >= len(l)/2: return
l[first], l[last] = l[last], l[first]
reverse(l, first+1, last-1)
mylist = [1,2,3,4,5]
print mylist
reverse(mylist)
print mylist
Рекурсивная функция для обращения списка.
def reverseList(lst):
#your code here
if not lst:
return []
return [lst[-1]] + reverseList(lst[:-1])
print(reverseList([1, 2, 3, 4, 5]))
выглядит проще:
def reverse (n):
if not n: return []
return [n.pop()]+reverse(n)
Возьмите первый элемент, рекурсивно переверните остальную часть списка и добавьте первый элемент в конец списка.
def reverseList(listName,newList = None):
if newList == None:
newList = []
if len(listName)>0:
newList.append((listName.pop()))
return reverseList(listName, newList)
else:
return newList
напечатать обратный список ([1,2,3,4]) [4,3,2,1]
Использование аргумента Mutable по умолчанию и рекурсии:
def hello(x,d=[]):
d.append(x[-1])
if len(x)<=1:
s="".join(d)
print(s)
else:
return hello(x[:-1])
hello("word")
Дополнительная информация
x[-1] # last item in the array
x[-2:] # last two items in the array
x[:-2] # everything except the last two items
Часть рекурсии - hello(x[:-1]), где функция приветствия снова вызывается после x[:-1]
Это также изменит вложенные списки!
A = [1, 2, [31, 32], 4, [51, [521, [12, 25, [4, 78, 45], 456, [444, 111]],522], 53], 6]
def reverseList(L):
# Empty list
if len(L) == 0:
return
# List with one element
if len(L) == 1:
# Check if that's a list
if isinstance(L[0], list):
return [reverseList(L[0])]
else:
return L
# List has more elements
else:
# Get the reversed version of first list as well as the first element
return reverseList(L[1:]) + reverseList(L[:1])
print A
print reverseList(A)
Вы можете уменьшить глубину рекурсии вдвое, поменяв местами первый и последний элементы сразу и рекурсивно вызвав rev в середине списка:
lks=[2,7,3,1,9,6,5]
def rev(lks):
if len(lks)<2:
return lks
return [lks[-1]]+rev(lks[1:-1])+[lks[0]]
print(rev(lks))
Ответ, который вы ищете, находится внутри функции. Остальное просто для того, чтобы увидеть (или если вы хотите сравнить) время, затрачиваемое различными алгоритмами.
import time
import sys
sys.setrecursionlimit(10**6)
def reverse(ls1):
if len(ls1) <= 1:
return ls1
else:
ls1[0], ls1[-1] = ls1[-1], ls1[0]
return [ls1[0]] + reverse(ls1[1:-1]) + [ls1[-1]]
ls = [*range(2000)]
start_time = time.time()
print(reverse(ls))
stop_time = time.time()
print(f"Total time taken: {(stop_time - start_time) * 1000} msec.")
Почему бы и нет:
a = [1,2,3,4,5]
a = [a[i] for i in xrange(len(a)-1, -1, -1)] # now a is reversed!
если это список чисел, то проще всего его изменить. Это также будет работать для строк, но не рекомендуется.
l1=[1,2,3,4]
l1 = np.array(l1)
assert l1[::-1]==[4,3,2,1]
если вы не хотите сохранять его как массив numpy, вы можете передать его в список как
l1 = [*l1]
опять же, я не рекомендую его для списка строк, но вы могли бы, если бы действительно хотели.