Генеративная рекурсия для поиска подсписка с максимальной суммой

Я пытаюсь решить проблему генеративной рекурсии в Python. Вопрос:

  • в списке, состоящем из целых чисел, найдите смежный подлист, который имеет самая большая сумма и верните эту сумму.
  • например, если данный список [-2, 1, -3, 4, -1, 2, 1, -5, 4], смежный подсписок, который имеет наибольшую сумму [4, -1, 2, 1], который имеет сумму 6

Я должен следовать заданному алгоритму для решения find_max:

  1. разделить данный список (в середине) на два: L_left и L_right.
  2. возвращает максимальное значение следующего 3:
    • максимальная сумма любого подсписка полностью находится в L_left (используя рекурсивный вызов find_max).
    • максимальная сумма любого подсписка полностью находится в L_right (используя рекурсивный вызов find_max).
    • максимальный подлист, который перекрывает L_left и L_right; т. е.,
      • во-первых: найти max сумма любого подсписка, начинающегося с середины (влево) и заканчивающегося в какой - то точке слева от середины!--5-->
      • Second: найти максимальную сумму любого подсписка, начиная с середины (в направлении справа) и заканчивается в какой-то точке справа от середины
      • наконец: добавьте две максимальные суммы.

я попробовал следующее:

def find_max(L):
    length = len(L)
    mid_index = length/2
    if length == 1:
        return L[0]
    else:
        left = find_max(L[0:(length/2)])
        right = find_max(L[(length/2):length])
        max_subset = max(left,right,left+right)
        return max_subset

Это может решить для списков длины 2. Как могу ли я расширить это, чтобы работать со списком с большим количеством элементов?

1 ответов


вы не подумали о следующем:

  • другой базовый случай: L является []
  • левая половина и правая половина должны быть последовательными.
    • согласно вашему коду, если L и [2, -5, 3], в первой рекурсии, left + right даст 5.

def find_max(L):
    length = len(L)
    mid_index = length/2
    if length == 0:
        return 0
    elif length == 1:
        return max(L[0], 0)

    left = find_max(L[:mid_index])
    right = find_max(L[mid_index:])

    left_half = right_half = 0
    # to the left
    accum = 0
    for x in L[mid_index-1::-1]:
        accum += x
        left_half = max(left_half, accum)

    # to the right
    accum = 0
    for x in L[mid_index:]:
        accum += x
        right_half = max(right_half, accum)

    return max(left, right, left_half + right_half)


assert find_max([]) == 0
assert find_max([-1]) == 0
assert find_max([1, 2, 3]) == 6
assert find_max([2, -5, 3]) == 3
assert find_max([-5, 1, 4, -2, 2, -1, 2, -3, 1, -3, 4]) == 6

без цикла for:

def sum_max(L, accum=0, max_value=0):
    if not L:
        return max_value
    accum += L[0]
    return sum_max(L[1:], accum, max(max_value, accum))

def find_max(L):
    ...
    left_half = sum_max(L[mid_index-1::-1])
    right_half = sum_max(L[mid_index:])
    ...