AkiVaMu Just tiny things come to mind...

Big O notation overview by example

This is great article of basic things about big O notation. Big O notation is used for describing the complexity of algorithm, or the cost of doing something in worst case. Just want to sum up here.

O(1) - constant cost

Doing something always costs the same constant amount of effort, no matter how difference input is.

bool IsFirstElementNull(IList<string> elements)
{
    return elements[0] == null;
}

O(N) - linear cost

Cost of algorithm linearly depends on size of input.

bool ContainsValue(IList<string> elements, string value)
{
    foreach (var element in elements)
    {
        if (element == value) return true;
    }

    return false;
}

In the best case, this algorithm takes 1 effort (comparison) to return result.
In the worst case, this algorithm takes n effort (length of array) to return result.
So it is O(N).

O(N2)

bool ContainsDuplicates(IList<string> elements)
{
    for (var outer = 0; outer < elements.Count; outer++)
    {
        for (var inner = 0; inner < elements.Count; inner++)
        {
            // Don't compare with self
            if (outer == inner) continue;

            if (elements[outer] == elements[inner]) return true;
        }
    }

    return false;
}

In the worst case, this algorithm takes n * n effort to return result.
It takes n iterations to go through all items in outer loop. For each iteration, need again go through all items in inner loop. It take n * n steps. So it is O(N2).
Simple words:

  • 2 layers of loop: O(N2)
  • 3 layers of loop: O(N3)
  • 4 layers of loop: O(N4)
  • and so on

O(2n)

int test(int number)
{
    if (number == 0) return number;

    return test(number - 1) + test(number - 1);
}

Cost will doubles each time we increase size of data by 1. Because each step will call 2 function recursively:

  • number = 0: 1 step (return expression)
  • number = 1: 2 steps i.e. 2 function calls test(0)
  • number = 2: 4 steps i.e. 2 function calls test(1), each has 2 function calls test(0)
  • number = 3: 8 steps i.e. 2 function calls test (2), each has 2 test(1) and each has 2 test(0)

O(log(n))

Quite hard to explain by word. Let’s see this example from SOF:

while (n > 0) {
   n/=2; 
}

Demonstration

Iteration n
0 n
1 n/2
2 n/4
k n/2k

2k = n -> k = log(n)
So we have O(log(n))