I had a job interview today. During it I was asked to write down an algorithm that will reverse a list. First I offered the answer using the reversed() method:
How about something like that:
x = [1, 2, 3, 4, 5]
for i in xrange(len(x) / 2):
x[i], x[-i - 1] = x[-i - 1], x[i]
print(x)
The idea is to swap array elements from opposite directions
One simple algorithm that could be easily ported to other languages would be:
x = [1,2,3,4,5]
y = []
for i in len(x):
y.append(x[len(x) - 1 - i])
Or using an iterator. This could be easily ported to be used with a chained list where you don't know the length:
x = [1,2,3,4,5]
y = []
x_iterator = iter(x)
try:
while (1):
y.insert(0, x_iterator.next())
except:
print y
Or a more pythonic version with insert:
x = [1,2,3,4,5]
y = []
for elem in x:
y.insert(0, elem)
I like this way:
def reverse(arr):
for i in range(len(arr) / 2):
arr[-i-1], arr[i] = arr[i], arr[-i-1]
Basically iterating through the first half of the array and swapping i
and len(i)-i-1
.
I'm assuming your interviewer didn't want you to use built-in Python methods, but an algorithm that's more language-agnostic. Something like:
lst = [1,2,3,4,5]
lst2 = []
while len(lst) > 0:
lst2.append(lst.pop())
or
lst2 = [lst.pop() for _ in lst[:]]
def reverse(text):
rev = []
for let in range(len(text),0,-1):
rev.append(text[let-1])
return ''.join(rev)
I guess your interviewer wanted to hear something like this:
A straightforward way to revert a list is to find out its length, then iterate from len-1 downto 0 and append the i-th element to the result. This approach works fine with real lists, but how can we revert a generator, i.e. something whose length is not known and cannot be found? (Good pythonistas use generators and yields instead of lists and returns).
Here's where we need a data structure known as "stack". A stack is like, well, a stack of things, like plates, put on the top of each other.
Whatever you put last comes out first, whatever was put first comes out last. So, our strategy will be like this:
Stacks can be programmed in python using lists, where .append
puts an item on the top of the stack, and .pop
removes the last thing off the stack:
def reverse(it):
stack = []
for item in it:
stack.append(item)
while stack:
yield stack.pop()
Of course, Python already has a built-in stack, and it's the stack of call frames. We can use that instead of the simulated one above, which leads us to the following recursive solution:
def reverse(it):
head = next(it)
for item in reverse(it):
yield item
yield head
in python3, this is even more elegant:
def reverse(it):
head = next(it)
yield from reverse(it)
yield head
Again, this works with arbitrary iterables, whose length is unknown at the call time.