包含一个列表并返回两个列表的递归函数

时间:2018-11-12 21:19:57

标签: python list recursion

要求我定义一个递归函数,该函数接受一个列表,然后在其他两个列表之间以这种方式分配该列表的值 这两个列表中每一个的总和,您会得到两个彼此接近的结果。

示例

如果我跑步:

print(proximity_lists([5, 8, 8, 9, 17, 21, 24, 27, 31, 41]))

我回来了两个列表:

[31, 27, 21, 9, 8]          #sum = 96

[41, 24, 17, 8, 5]          #sum = 95

这就是我的方法,但是我无法理解如何在递归函数中返回两个列表。到目前为止,我对必须返回一份清单的条件感到满意。

到目前为止,这是我的代码:

def proximity_lists(lst, lst1 = [], lst2 = []):
    """
    parameters : lst of type list;
    returns : returns two lists such that the sum of the elements in the lst1
              is in the proximity of the sum of the elements in the lst2
    """
    if not lst:
        if abs(sum(lst1)-sum(lst2)) in range(5):         
            return lst1, lst2
    else:
        return {Not sure what to put here} + proximity_lists(lst[1:])

range()而言,只要它是彼此之间可以接近的最接近,就可以对参数进行任何处理。我选择5是因为根据上面的示例输出,它们之间的差是1。

我需要补充的是,这必须在没有任何模块帮助的情况下完成,而必须使用简单的函数来完成。

3 个答案:

答案 0 :(得分:1)

就性能(指数复杂度)而言,这可能不是最佳解决方案,但也许可以让您入门:

def proximity_lists(values):
    def _recursion(values, list1, list2):
        if len(values) == 0:
            return list1, list2
        head, tail = values[0], values[1:]
        r1, r2 = _recursion(tail, list1 + [head], list2)
        s1, s2 = _recursion(tail, list1, list2 + [head])
        if abs(sum(r1) - sum(r2)) < abs(sum(s1) - sum(s2)):
            return r1, r2
        return s1, s2

    return _recursion(values, [], [])

values = [5, 8, 8, 9, 17, 21, 24, 27, 31, 41]
s1, s2 = proximity_lists(values)
print(sum(s1), sum(s2))
print(s1)
print(s2)

96 95
[24, 31, 41]
[5, 8, 8, 9, 17, 21, 27]

如果不能使用包装函数,则直接调用_recursion(values, [], [])

答案 1 :(得分:0)

您可以找到第一个列表的原始输入的所有排列,并对原始列表进行过滤以获得第二个。该答案假定“紧密接近”是指两个列表的总和之间的差值小于或等于1

from collections import Counter

def close_proximity(d, _dist = 1):
  def _valid(c, _original):
    return abs(sum(c) - sum([i for i in _original if i not in c])) <= _dist
  def combos(_d, current = []):
    if _valid(current, _d) and current:
      yield current
    else:
      for i in _d:
        _c1, _c2 = Counter(current+[i]), Counter(_d)
        if all(_c2[a] >= b for a, b in _c1.items()):
          yield from combos(_d, current+[i])
  return combos(d)

start = [5, 8, 8, 9, 17, 21, 24, 27, 31, 41]
t = next(close_proximity(start))
_c = [i for i in start if i not in t]
print(t, _c, abs(sum(t) - sum(_c)))

输出:

[5, 8, 8, 9, 17, 21, 27] [24, 31, 41] 1

答案 2 :(得分:0)

  

我无法理解如何返回一个列表中的两个列表   递归函数。

这是一个产生原始结果的简单解决方案,但是没有额外的参数,内部函数等。它只是不断从下一个可用值中扩充较小的列表:

def proximity_lists(array):
    if array:
        head, *tail = array

        a, b = proximity_lists(tail)

        ([a, b][sum(b) < sum(a)]).append(head)

        return [a, b]

    return [[], []]

用法

>>> proximity_lists([5, 8, 8, 9, 17, 21, 24, 27, 31, 41])
[[41, 24, 17, 8, 5], [31, 27, 21, 9, 8]]
>>>