Производительность рекурсии массивов и списков

Я решаю задачу «Лучшее время для покупки и продажи акций» на leetcode https://leetcode.com/problems/best-time-to-buy-and-sell-stock/description/ с 2 подходами:

  1. Сначала я преобразовал Array в List и рекурсивно обрабатываю список:

     def maxProfit(prices: Array[Int]): Int = {
     @tailrec
     def maxProfitHelp(prices: List[Int], maxProfit: Int, lastBuy: Int): Int = {
       prices match {
         case Nil => maxProfit
         case head :: tail => if (head > lastBuy)  {
           maxProfitHelp(tail, Math.max(maxProfit, head - lastBuy), lastBuy)
         } else {
           maxProfitHelp(tail, maxProfit, head)
         }
       }
     }
    
     val listPrices = prices.toList
     maxProfitHelp(listPrices.tail, 0, listPrices.head)
    }
    

Это дало время производительности 962 мс. (Память: 71,70 МБ)

  1. Во-вторых, я попытался обработать исходный массив тем же рекурсивным способом.

    def maxProfitWithoutList(prices: Array[Int]): Int = {
      @tailrec
      def maxProfitHelp(prices: Array[Int], maxProfit: Int, lastBuy: Int): Int = {
       prices match {
        case c if c.isEmpty => maxProfit
        case c => if (c.head > lastBuy)  {
         maxProfitHelp(c.tail, Math.max(maxProfit, c.head - lastBuy), lastBuy)
         } else {
            maxProfitHelp(c.tail, maxProfit, c.head)
         }
       }
     }
    
      maxProfitHelp(prices.tail, 0, prices.head)
    }
    

А время выполнения составляет 9134 мс. (Память: 75,47 МБ)

Таким образом, сложность рекурсии Array в 10 раз хуже (!), чем рекурсии List!

Почему это случилось?

Отвечает ли это на ваш вопрос? Выполнение хвостовой функции для массивов Scala

yangzai 16.04.2024 13:43

Потому что взятие хвоста Array копирует всю память. Не используйте Arrays как новичок, у них много проблем, одна из них ужасна в производительности, если вы не используете их должным образом.

Luis Miguel Mejía Suárez 16.04.2024 15:57
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
2
96
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
  1. Раньше при использовании leetcode я довольно часто сталкивался с тем, что даже один и тот же код имел совершенно разное время выполнения (хотя и не в 10 раз), поэтому попробуйте отправить одно и то же решение несколько раз или лучше использовать соответствующие инструменты для сравнительного анализа.

  2. Насколько я вижу, Array.tail возвращает Array[T], что означает, что должен быть создан новый массив и скопированы в него данные (следовательно, O(n)), в отличие от List, который:

    неизменяемый класс связанного списка

    а это значит, что операция tail должна быть очень быстрой (O(1)).

Другие вопросы по теме