Как решить проблему с ошибкой "Превышен лимит памяти"?

Мой код на Python превышает лимит памяти в 64 Мб. <br/> <br/> Передо мной стоит задача: найти из списка сторон такие, чтобы получаемый между ними прямоугольник имел максимальную площадь. Функционально код работает корректно, но он не укладывается в ограничения по памяти. <br/> <br/> <pre><code class="python">length = input().split()
data = [int(x) for x in length]
data_copy = data


n = len(data)
result_lens = []

for i in range(n):
    for j in range(i+1, n):
        pair_width = abs(i - j)
        if data[i] &lt; data[j]:
            pair_height = data[i]
        else:
            pair_height = data[j]
        result_lens.append(pair_height*pair_width)


print(max(result_lens))</code></pre> <br/> Этот алгоритм оказался самым эффективным из всех, которые я пробовал, однако я не знаю, как сократить потребление памяти. Использование сторонних библиотек запрещено. <br/> <br/> python
  • 20 сентября 2024 г. 13:53
Ответы на вопрос 3
Ваш текущий код использует список `result_lens` для хранения площадей всех возможных прямоугольников, что приводит к большому потреблению памяти, особенно если длина входного списка велика. Вместо того, чтобы хранить все площади в списке, вы можете вычислять максимальную площадь на лету, сохраняя только текущее максимальное значение. Вот как вы можете переписать ваш код:

```python
length = input().split()
data = [int(x) for x in length]

n = len(data)
max_area = 0

for i in range(n):
    for j in range(i + 1, n):
        pair_width = abs(i - j)
        pair_height = min(data[i], data[j])  # используем минимальное значение для высоты
        area = pair_height * pair_width
        if area > max_area:
            max_area = area

print(max_area)
```

### Изменения:
1. Убрали список `result_lens`, так как он не нужен.
2. Вместо этого, в каждом цикле обновляем только `max_area`, если текущая площадь больше.

### Пояснение:
- Мы сохраняем только текущее максимальное значение площади, что значительно уменьшает использование памяти.
- Временная сложность алгоритма остается прежней — O(n^2), но объем памяти, используемой в процессе, снижен до O(1), что очень важно в условиях ограничений.

Эта оптимизация позволит вашему коду работать в рамках выделенного лимита памяти.
1. Чтобы найти максимум, не надо запоминать все значения, достаточно помнить максимальное. 
2. Эта задача решается гораздо проще со сложностью O(n), а не O(n
Берём два крайних отрезка (left = 0 и right = n-1), вычисляем площадь прямоугольника (right - left) * min(length[left], length[right]).
Учитывая, что при сдвиге границ к центру расстояние (right - left) уменьшается, для увеличения площади необходимо увеличение min(length[left], length[right]). Поэтому берём ту границу left или right, длина отрезка для которой меньше, и начинаем двигать к центру, пока длина нового отрезка не станет больше предыдущей (length[left'] > length[left] или length[right'] > length[right]).
Вычисляем новую площадь. Если она больше предыдущей, запоминаем положения отрезков. Повторяем процедуру сдвигания.
Убираем создание списка result_lens, чтобы не сохранять промежуточные результаты. 
Вместо этого вычисляем площадь каждой пары на лету и сразу же обновляем значение максимальной площади в переменной max_area.
Убираем ненужное копирование списка data_copy.

Для понимания изначально сложность алгоритма по памяти составляла O(n^2), но поскольку мы оптимизировали алгоритм, убрав сохранение промежуточных данных в список и используя одну лишь переменную для хранения максимальной площади, сейчас сложность составляет O(1)

length = input().split()
data = [int(x) for x in length]

n = len(data)
max_area = 0

for i in range(n):
    for j in range(i + 1, n):
        pair_width = abs(i - j)
        pair_height = min(data[i], data[j])
        max_area = max(max_area, pair_height * pair_width)

print(max_area)
Похожие вопросы