2

The "oneToEach" function adds 1 to each element of a List[Int]. The first function is not tail recursive, whereas the latter is.

If I had a one million length List[Int] that I passed in to these 2 functions, which one would perform better? Better = faster or less resource usage.

// Add one to each element of a list
def oneToEach(l: List[Int]) : List[Int] =
  l match {
   case Nil => l
   case x :: xs => (x + 1) :: oneToEach(xs)
}

...

def oneToEachTR(l: List[Int]) : List[Int] =  {
  def go(l: List[Int], acc: List[Int]) : List[Int] = 
     l match {
       case Nil => acc
       case x :: xs => go(xs, acc :+ (x + 1))
     }
  go(l, List[Int]())
}

If I understand, the first function has algorithmic complexity of O(n) since it's necessary to recurse through each item of the list and add 1.

For oneToEachTR, it uses the :+ operator, which, I've read, is O(n) complexity. As a result of using this operator per recursion/item in the list, does the worst-case algorithm complexity become O(2*n)?

Lastly, for the million-element List, will the latter function perform better with respect to resources since it's tail-recursive?

Community
  • 1
  • 1
Kevin Meredith
  • 41,036
  • 63
  • 209
  • 384

1 Answers1

4
  1. Regarding

    For oneToEachTR, it uses the :+ operator, which, I've read, is O(n) complexity. As a result of using this operator per recursion/item in the list, does the worst-case algorithm complexity become O(2*n)?

    no, it becomes O(n^2)

  2. Tail recursion won't save a O(n^2) algorithm vs O(n) for sufficiently large n; 1 million is certainly sufficient!


Why O(n^2)?

  • You've got a list of n elements.
  • The first call to :+ will traverse 0 elements (acc is is initially empty) and append 1: 1 operation.
  • The second call will traverse 1 element and append 1: 2 operations
  • The third call.. 2 elements + append 1: 3 operations
  • ...
  • The sum of all "operations" is 1 + 2 + 3 + ... + n = n(n+1)/2 = (1/2)n^2 + n/2. That's "in the order of" n^2, or O(n^2).
Richard Sitze
  • 8,262
  • 3
  • 36
  • 48