【问题标题】:Alternate Python List Reverse Solution Needed需要备用 Python 列表反向解决方案
【发布时间】:2015-02-06 15:59:18
【问题描述】:

我今天有一个工作面试。在此期间,我被要求写下一个可以反转列表的算法。首先,我使用 reversed() 方法提供了答案:

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

进行采访的高级开发人员问我是否知道另一种方法,我在此基础上写下了另一种已知的切片方法:

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

不幸的是,他也对这个解决方案不满意,并要求我考虑另一个解决方案。几分钟后,我说我想不出更好的了。他说这对他们的标准来说不够好。

我完全同意他的意见,并且对我的代码进行更多练习没有问题。我的问题是,如果有的话,我不知道有什么更好的解决方案。是否还有其他更“程序员”的方式...唯一想到的其他事情就是递归,但是我是在面试完成后才想到的。 谢谢。

【问题讨论】:

  • 我想他是在找你建议一种算法,而不是预制的(和正确的!)Python 方法。
  • 你问他在找什么吗?
  • 看来是这样,我没有跳出框框思考。这是我第一次接受这种职位的面试。我太紧张了,想着我是多么愚蠢,而不是要求他澄清。

标签: python list reverse


【解决方案1】:

你的两个答案在 python 方面都很好,所以面试官一定是在要求你实现自己的方法:

使用递归:

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

或者一个列表 comp 和 range 从 l -1 的长度开始并反向:

l = list(range(100))

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

使用 itertools.count:

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

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

为了提高效率,请使用生成器表达式:

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

for ele in rev:
    print(ele)

或者使用地图:

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]

没有对 map 的 list 调用,我们将得到一个可以在 python3 中迭代的 map 对象,您可以在 python2 中使用itertools.imap 来实现类似的结果

【讨论】:

  • 有趣的答案。谢谢你。我想我是在考虑给出最 Pythonic 的答案,而不是尝试发明自己的解决方案。
  • @user44772,就像我在 python 方面说的那样,你的答案很好,特别是在效率方面使用 reversed 所以唯一真正合乎逻辑的解释是面试官希望你想出替代的非内置方法跨度>
  • 前两个是不同的方法。其他的看起来很有趣,但几乎相同,我认为唯一不同的方法是交换列表项或将它们弹出
【解决方案2】:

我猜你的面试官想听到这样的话:

恢复列表的一种直接方法是找出它的长度,然后从 len-1 向下迭代到 0 并将第 i 个元素附加到结果中。这种方法适用于真实列表,但我们如何恢复生成器,即长度未知且无法找到的东西? (好的 pythonistas 使用生成器和 yield 而不是列表和返回)。

这里我们需要一个称为“堆栈”的数据结构。一堆就像,嗯,一堆东西,像盘子,放在彼此的顶部。

你放什么last出来first,放什么first出来last。所以,我们的策略是这样的:

  • 当有项目时,将每个项目放入堆栈
  • 当堆栈不为空时,将项目从堆栈中弹出并返回

可以在 python 中使用列表对堆栈进行编程,其中.append 将一个项目放在堆栈顶部,.pop 将最后一个项目从堆栈中移除:

def reverse(it):
    stack = []
    for item in it:
        stack.append(item)
    while stack:
        yield stack.pop()

当然,Python 已经有一个内置堆栈,它是调用帧的堆栈。我们可以使用它代替上面的模拟,这导致我们得到以下 recursive 解决方案:

def reverse(it):
    head = next(it)
    for item in reverse(it):
        yield item
    yield head

在python3中,这更加优雅:

def reverse(it):
    head = next(it)
    yield from reverse(it)
    yield head

同样,这适用于任意迭代,其长度在调用时未知。

【讨论】:

    【解决方案3】:

    一种可以轻松移植到其他语言的简单算法是:

    x = [1,2,3,4,5]
    y = []
    for i in len(x):
      y.append(x[len(x) - 1 - i])
    

    或者使用迭代器。这可以很容易地移植到您不知道长度的链表中:

    x = [1,2,3,4,5]
    y = []
    x_iterator = iter(x)
    try:
      while (1):
        y.insert(0, x_iterator.next())
    except:
      print y
    

    或者是一个更 Pythonic 的版本:

    x = [1,2,3,4,5]
    y = []
    for elem in x:
      y.insert(0, elem)
    

    【讨论】:

    • 是的,列表理解,但我替换了示例,它很糟糕。
    【解决方案4】:

    我假设你的面试官不希望你使用内置的 Python 方法,而是一种与语言无关的算法。比如:

    lst = [1,2,3,4,5]
    lst2 = []
    
    while len(lst) > 0:
        lst2.append(lst.pop())
    

    lst2 = [lst.pop() for _ in lst[:]]
    

    【讨论】:

    • 他很可能想要这样的东西,但是在那一刻我有点紧张,而且在没有在线帮助的情况下在一张纸上编码也感觉很不寻常。然而,对于未来的一些采访来说,这是一个很好的教训。谢谢亚当。
    • while len(lst) > 0 可以替换为while lst
    【解决方案5】:

    这样的事情怎么样:

    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)
    

    这个想法是从相反的方向交换数组元素

    【讨论】:

    • 我喜欢 xrange()。这会让面试官接下来问 range() 和 xrange()。
    【解决方案6】:

    我喜欢这种方式:

    def reverse(arr):
        for i in range(len(arr) / 2): 
            arr[-i-1], arr[i] = arr[i], arr[-i-1]
    

    基本上遍历数组的前半部分并交换ilen(i)-i-1

    【讨论】:

      【解决方案7】:
      def reverse(text):
        rev = []
        for let in range(len(text),0,-1):
          rev.append(text[let-1])
        return ''.join(rev)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-05-23
        • 2016-03-31
        • 1970-01-01
        • 2023-01-26
        • 2018-12-11
        • 1970-01-01
        • 2017-10-02
        • 2015-06-04
        相关资源
        最近更新 更多