简体   繁体   中英

Alternate Python List Reverse Solution Needed

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:

    x = [1,2,3,4,5]
    y = reversed(x)
    for i in y:
        print i

The senior developer conducting the interview asked me if I know another way, upon which I wrote down the other known method with slicing:

   x = [1,2,3,4,5]
   y = x[::-1]

Unfortunately he was unhappy with this solution as well and asked me to think of another one. After few minutes I said I could not come up with a better one. He said that this was not good enough for their standards.

I am perfectly fine with his opinion and have no problem practicing more on my code. My question is, what is a better solution that I am not aware of, if there is one. Could there be some other more 'programmer' way...Only other thing that comes to mind is recursion, however I thought of it only after the interview was already done. Thanks.

Both your answers are good in terms of python so the interviewer must have been asking you to implement your own method:

Using recursion:

def recur_rev(l):
    return recur_rev(l[1:]) + l[:1] if l else l

Or a list comp and range starting at the length of l -1 and going in reverse:

l = list(range(100))

print([l[ind] for ind in range(len(l)-1,-1,-1)])

Using itertools.count:

from itertools import count
cn = count(len(l) -1, -1)

print([l[next(cn)] for ele in l])

For efficiency use a generator expression:

rev  = (l[next(cn)] for ele in l)

for ele in rev:
    print(ele)

Or using map:

print(list(map(l.__getitem__,range(len(l)-1,-1,-1)))) # list needed for python3

[99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

without the list call on map we will get a map object we can iterate over in python3, you can use itertools.imap in python2 to achieve a similar result

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, ie 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:

  • while there are items, put each item onto the stack
  • while the stack is not empty, pop items off the stack and return them

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.

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'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[:]]

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

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 .

def reverse(text):
  rev = []
  for let in range(len(text),0,-1):
    rev.append(text[let-1])
  return ''.join(rev)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM