I have been trying to learn algorithms for a long time now and I am really struggling with the math part and don't know what to do. I only know very basic math, so my question is what do I have to know to be able to understand BigO notation? For example,
$f(n) = O(g(n))$ if there are positive constants $n_0$ and $c$ such that to the right of $n_0$, the value of $f(n)$ always lies on or below $c\cdot g(n)$.Big Oh Examples
$3n^2 - 100n + 6 = O(n^2)$ because $3n^2 > 3n^2+ 100n + 6$
$3n^2 - 100n + 6 = O(n^3)$ because :$n^3 > 3n^2 - 100n + 6$
$3n^2 - 100n + 6 6= O(n)$ because $c \cdot n < 3n^2$ when $n > c$
source pdf: http://www3.cs.stonybrook.edu/~algorith/video-lectures/2007/lecture2.pdf mp4: http://www3.cs.stonybrook.edu/~algorith/video-lectures/2012/CSE373_(CSE373-01)_2013_Spring_2013-01-31.html
I am totally lost. What should I do to learn this? And I would be greatful if someone explain what it means.
One almost equivalent way to understand big-O is if $f(x)/g(x)$ becomes closer and closer to a non-negative constant (even zero) as $x$ grows then $f(x) = O(g(x))$. Thus it means they either have the same fundamental growth rate, or $g(x)$ has a fundamentally faster growth rate (in the case that $f(x)/g(x)$ becomes closer and closer to zero). But in terms of $f(x)/g(x)$, as long as you can show that it's less than some positive constant for $x$ large enough, this is the exactly the same as big-O.
In computer science, the reason why we use big-O is that we want to express the fundamental growth rate of the running time or space used of an algorithm/program, in terms of the size $x$ of the input, without worrying about details about whether one CPU operation takes twice as long as some other operation, or whether the true growth rate of algorithm running time/space is different in an additive way that becomes less and less important as $x$ increases. We want a very simple expression (like $O(n^3)$) that captures the "essence" of the running time. We don't mind if the actual running time is say, 10 times longer as $x$ grows, just as long as it's only a bounded constant factor multiplier as $x$ grows. As long as the constant is not too large, we can get pretty good ideas about how large on an input we can handle if we know the big-O.
One way to approach big-O in practice when doing calculations is by memorizing some general rules (assuming you understand the rough concept of what big-O means):
If $f(x) = O(g(x))$ and $h(x)$ is an increasing function, then $h(f(x)) = O(h(g(x)))$ and $f(h(x)) = O(g(h(x)))$.
If you are given a weighted sum of $k$ functions $c_1f_1(x) + c_2f_2(x) + c_3f_3(x) + \ldots c_kf_k(x)$ and each function $f_i = O(g(x))$ then the sum is also $O(g(x))$.
If $f_1(x) = O(g_1(x))$ and $f_2(x) = O(g_2(x))$ for positive $f_1,f_2$, then $f_1(x) \cdot f_2(x) = O(g_1(x) \cdot g_2(x))$
$x^c = O(a^x)$ for any $c$ and any $a > 1$.
$(\log x)^c = O(x^d)$ for any $c, d > 0$.
The last two are important in certain cases, and can be shown by L'Hopital's rule.