|
||||||||||||||||||||||||
|
Determining Big-O Complexity
As a developer you will often wonder how complex is an algorithm or piece of code you are using, i.e. as the size of its input increases, at what rate does its use of computing resources (usually CPU cycles or memory) increase? In this sense any function of a program can be considered a mathematical function of x where x is the input to the function and f(x) is the number of computing resources used.
The symbol O denotes an asymptotic upper bound for a function in the form of another function that "bounds" it. So,
How to determine the O of an algorithm
The most important thing to remember when determining the O is that "stronger" terms of a function dominate its upper bound as the x get larger. So, for example, the function x + x2 has an O(x2) simply because when x gets large enough the x2 term of the function dominates.
The second most important thing to remember is that the O of your algorithm ultimately depends on the kind of programming statements it involves as well as how they are combined. The catch here is a statement that appears simple (i.e. O(1)) may actually involve some kind of lib or system call that is much more complex; so, look out for that! Note that O(1) basically means constant number of resources regardless of the size of input, e.g. a computation like x + 5 somewhere in your program basically always performs a integer addition regardless of how big x is.
Assuming all statements demoted as such are of O(1), here are some very basic rules:
- Sequence of statements: O(1)
- Loop of statements: O(n) where n is the number of loop executions. Note here that we assume n is the input of the function. If n is not related to the function's input then the loop is O(1) , i.e. constant.
- Nested loop of statements: O(n*m) where n is the times the outer loop executes and m is the times the inner loop executes. Again, for this to make sense bothn and m must be somehow related to the input of the function. If n = m then we get an O(n2). In fact, this special case is, among others, the case of the well known Selection Sort algorithm (a quite inefficient algorithm actually but makes for a good N2 example)
Some other common algos and their complexity orders, in order of growing magnitude, follow (from Wikipedia):
| Big O Notation | Name | Example |
|---|---|---|
| constant | Determining if a number is even or odd | |
| iterated logarithmic | The find algorithm of Hopcroft and Ullman on a disjoint set | |
| logarithmic | Finding an item in a sorted list with the binary search algorithm | |
| polylogarithmic | Deciding if n is prime with the AKS primality test | |
| fractional power | searching in a kd-tree | |
| linear | Finding an item in an unsorted list | |
| linearithmic, loglinear, or quasilinear | Sorting a list with heapsort, computing a FFT | |
| quadratic | Sorting a list with insertion sort, computing a DFT | |
| polynomial, sometimes called algebraic | Finding the shortest path on a weighted digraph with the Floyd-Warshall algorithm | |
| exponential, sometimes called geometric | Finding the (exact) solution to the traveling salesman problem (under the assumption that P ≠ NP) | |
| factorial, sometimes called combinatorial | Determining if two logical statements are equivalent [1], traveling salesman problem, or any other NP-complete problem via brute-force search | |
| double exponential | Finding a complete set of associative-commutative unifiers [2] |




thanks, but not enough
thanks, but not enough specifics on how to find it to be of much use....
yeah
yeah, true. I hope to expand the article next time I have to do some serious O calcs.
Yeah, definitely helps with
Yeah, definitely helps with the basics, but doesn't help me solve algorithm complexity examples.
Thank you! It all starts with the basics...
I appreciate the elementary principles and explanations of Big ) complexity. Now I feel I can begin to make sense of sorting algorithms.
Thank you!
Post new comment