Question: I have this code, which is slightly different than the some of the other code with the same question on this site:

```
public void printAllRootToLeafPaths(Node node,ArrayList path) {
    if(node==null){
        return;
    }
    path.add(node.data);

    if(node.left==null && node.right==null)
    {
        System.out.println(path);
        return;
    }
    else {
        printAllRootToLeafPaths(node.left, new ArrayList(path));
        printAllRootToLeafPaths(node.right,new ArrayList(path));
    }      
}

```

Can someone explain WHY best case is O(nlogn)?
Worst case, the tree breaks down to a linked list and the array is copied 1+2+3+...+n-1+n times which is equivalent to n^2 so the time complexity is O(n^2).  

Best case array is being copied along every node in the path. So copying it looks like 1+2+3+...+logn. N/2 times. So why isn't the summation (logn)^2 if 1+2+3+...+n-1+n is n^2? Making the best case O(n(logn)^2)?

Answer: 
Yes, all that copying needs to be accounted for.

Those copies are not necessary; it's easy to write functions which either:

* use a (singly) linked list instead of ArrayList, or
* use a single ArrayList, overwriting previous paths when they're not needed any more.

With non-copying algorithms, the cost of the algorithm is the cost of printing the paths, which is the sum of the lengths of all paths from the root to a leaf. Copy the array on every call, makes the cost become the sum of the paths from the root to every *node*, rather than every leaf. (The fact that the array is copied twice is really not relevant to complexity analysis; it just means multiplying by a constant factor, which can be ignored.)

With the non-copying algorithm, the best case is a linear tree, with only one child per node. Then there is just one leaf with a path length of *N*, so the total cost is O(*N*). But that's a worst-case input if you're copying at every node; the node path lengths are successive integers, and the sum of node path lengths is quadratic.

For your algorithm, the best case is a perfectly-balanced fully-occupied tree. In a fully-occupied tree, there is one more leaf than non-leaf nodes; in other words, approximately half the nodes are leaves. In a perfectly-balanced tree, every node can be reached from the root in a maximum of log *N* steps. So the sum of path lengths to every node is O(*N* log *N*). (Some nodes are closer, but for computing big O we can ignore that fact. Even if we were to take it into account, though, we'd find that it doesn't change the asymptotic behaviour because the number of nodes at each depth level doubles for each successive level.) Because half the nodes are leaves, the cost of this input is O(*N* log *N*) with the non-copying algorithm as well.

Both algorithms exhibit worst-case quadratic complexity. We've already seen the worst-case input for the copying algorithm: a linear tree with just one leaf. For the non-copying algorithm, we use something very similar: a tree consisting of a left-linked backbone, where every right link is a leaf:

```
                         root
                          /\
                         /  \
                        /\   7
                       /  \
                      /\   6
                     /  \
                    /\   5
                   /  \
                  /\   4
                 /  \
                /\   3
               /  \
               1  2

```

Since that tree is fully-occupied, half its nodes are leaves, and they are at successively increasing distances, so that is again quadratic (although the constant multiplier is smaller.)
I think you're missing the time complexity of copying the entire array to a new one.

---

At root node: `one element is added, but 2 new arrays are created`.

At left child node of root node: `one element is added, but 2 new arrays are created with 2 elements`.

.
.
.

At last but one level: `one element is added, but 2 new arrays are created of size log n to base 2.`

At last level: one element is added, and the log n elements are printed.

---

So at each node there is one operation of adding an element to the list and one operation of either printing or duplicating a list of size (log h) - where h is the height of the node in the tree.

Since we are traversing through all the elements only once, total number of operations are: `n additions + Sum (log h1 + log h2 + log h3 + .... log hn)`

Where h1, h2, h3...hn are heights of each node.

Which is approximately `n + O(n log n)` `~` `O(n log n)`.