Write the algorithm in its functional form for running time. Each algorithm is different in this regard, and you will never have its true form --- only an estimate. You can get the estimate by looking at the code of the algorithm itself and counting the number of time units it takes for the algorithm to finish computing an input of size "n." Write this function as "f(n)." For example, a "for loop" that initiates at 1 and ends at n will have the function f(n) = n as its running time estimate.
Estimate an upper bound for f(n). An upper bound is a number that f(n) cannot pass after a large enough value of n. For example, if f(n) = n^3 + 10n + 3, a logical choice for an upper bound estimate would be c*n^3, where c is a constant greater than 1. This is a reasonable choice since c*n^3 is larger than the largest term in f(n).
Write the upper bound in mathematical notation. Write f(n) < upper bound. For the previous example, this is n^3 + 10n + 3 < c*n^3.
Prove that this inequality holds true for large values of n. Usually, this involves solving the inequality for c and checking if the result holds. In the example above, using algebra yields the inequality c > 1 + 10*n^-2 + 3*n^-3. For large n, the values with negative exponents go to zero, leaving c > 1. This inequality is true because it was stated that it was true when c was chosen.
If the inequality holds, the complexity of the algorithm is O(estimated upper bound without the constant). For the example, since the inequality held, the complexity is O(n^3). If the inequality does not hold, you must estimate a new upper bound and run the process again.