如何仅使用Python中的递归返回列表的奇数?

时间:2010-10-28 02:48:29

标签: python recursion

我不想使用while或for循环,只想使用递归来返回给定列表中的奇数。谢谢!

11 个答案:

答案 0 :(得分:9)

def find_odds(numbers):
  if not numbers:
    return []
  if numbers[0] % 2 == 1:
    return [numbers[0]] + find_odds(numbers[1:])
  return find_odds(numbers[1:])

无需额外的变量或参数。

答案 1 :(得分:7)

def only_odd(L):
    return L[0:L[0]&1]+only_odd(L[1:]) if L else L

这个版本要快得多,因为它避免复制L

def only_odd_no_copy(L, i=0):
    return L[i:i+(L[i]&1)]+only_odd_no_copy(L, i+1) if i<len(L) else []

这个只使用O(log n)堆栈空间

def only_odd_logn(L):
    x=len(L)/2+1
    return L[:L[0]&1] + only_odd2(L[1:x]) + only_odd_logn(L[x:]) if L else L

答案 2 :(得分:3)

def find_odds(numbers, odds):
    if len(numbers) == 0:
        return
    v = numbers.pop()
    if v % 2 == 1:
        odds.append(v)
    find_odds(numbers, odds)

odds = []
numbers = [1,2,3,4,5,6,7]
find_odds(numbers,odds)
# Now odds has the odd numbers
print odds

这是我运行时得到的测试结果

[7,5,3,1]

答案 3 :(得分:3)

考虑到python中默认的堆栈深度限制为1000,我真的不会使用递归。我知道上面有很多递归实现,所以这里是一个非递归的实现,它以python的方式进行:

print filter(lambda x: x % 2, range(0, 10))

为了完整起见;如果你真的必须在这里使用递归,那么我就去吧。这与Josh Matthews的版本非常相似。

def rec_foo(list):
    if not list:
        return []
    return ([list[0]] if list[0] % 2 else []) + rec_foo(list[1:])

print rec_foo(range(1, 10))

答案 4 :(得分:2)

这是另一种方法,它返回奇数列表而不是修改传入的列表。非常类似于GWW提供的但是我认为我会添加它以保证完整性。

def find_odds(numbers, odds):
    if len(numbers) == 0:
        return odds

    if numbers[0] % 2 == 1:
        odds.append(numbers[0])

    return find_odds(numbers[1:],odds)

print find_odds([1,2,3,4,5,6,7,8,9],[])

输出是:

[1, 3, 5, 7, 9]

答案 5 :(得分:2)

因为它是一个派对,我只是想我会用一个好的,明智的,真正的程序员 TM 解决方案。它是用emacs编写的,灵感来自gnibbler的答案。和他一样,它使用&1代替% 2(如果已经存在1,则将co_consts中的2添加为纯粹的颓废)并且仅当它是奇数时才使用那个漂亮的技巧来获取第一个元素,但是节省了一些时间,节省了大约5%的时间(在我的机器上,运行2.6.5在Linux2内核上使用GCC 4.4.3编译)。

from opcode import opmap
import types

opcodes = [opmap['LOAD_FAST'],      0,0,   #    L
           opmap['JUMP_IF_FALSE'],  24,0, 
           opmap['DUP_TOP'],
           opmap['LOAD_CONST'],     0,0,   #    0
           opmap['BINARY_SUBSCR'],  
           opmap['LOAD_CONST'],     1,0,   #    1
           opmap['BINARY_AND'],
           opmap['SLICE+2'],
           opmap['LOAD_GLOBAL'],    0,0,   #    odds
           opmap['LOAD_FAST'],      0,0,
           opmap['LOAD_CONST'],     1,0,
           opmap['SLICE+1'],
           opmap['CALL_FUNCTION'],  1,0,
           opmap['BINARY_ADD'],
           opmap['RETURN_VALUE']]

code_str = ''.join(chr(byte) for byte in opcodes)

code = types.CodeType(1, 1, 4, 0x1 | 0x2 | 0x40, code_str, (0, 1),
                      ('odds',), ('L',), '<nowhere>', 'odds',
                      0, '')

odds = types.FunctionType(code, globals())

答案 6 :(得分:1)

odds = []
def findOdds(listOfNumbers):
    if listOfNumbers[0] % 2 == 1:
        odds.append(listOfNumbers[0])
    if len(listOfNumbers) > 1:
        findOdds(listOfNumbers[1:])

findOdds(range(0,10))
print odds
# returns [1,3,5,7,9]

答案 7 :(得分:0)

>>> def fodds(alist, odds=None):
...     if odds is None: odds = []
...     if not alist: return odds
...     x = alist[0] # doesn't destroy the input sequence
...     if x % 2: odds.append(x)
...     return fodds(alist[1:], odds)
...
>>> fodds(range(10)) # only one arg needs to be supplied
[1, 3, 5, 7, 9] # same order as input
>>>

这个避免了列表复制开销,但代价是向后获得答案并且丑陋因素大幅增加:

>>> def fo(aseq, pos=None, odds=None):
...     if odds is None: odds = []
...     if pos is None: pos = len(aseq) - 1
...     if pos < 0: return odds
...     x = aseq[pos]
...     if x % 2: odds.append(x)
...     return fo(aseq, pos - 1, odds)
...
>>> fo(range(10))
[9, 7, 5, 3, 1]
>>>

答案 8 :(得分:0)

def odds(L):
    if L == []: 
        return []
    else:
        if L[0]%2:
            B = odds(L[1:])
            B.append(L[0])
            return B
        else:
            return odds(L[1:])

答案 9 :(得分:0)

嗯,还有很多其他的答案,但我认为我的最干净:

def odds(L):
   if not L: 
      return []
   return [L[0]] * (L[0] % 2) + odds(L[1:])

有趣的运动,但只是重申,不要在实践中递归地进行。

答案 10 :(得分:0)

因为我们都在做出贡献:

def odds(aList):
    from operator import lshift as l
    if aList and not aList[1:]:
        return aList if aList[-1] - l(aList[0]>>1, 1) else list()
    return odds(aList[:len(aList)/3+1]) + odds(aList                                     \
    [len(aList)/3+1:]) if aList else []