🚧 Big o cheatsheet expansion
This commit is contained in:
parent
75ab06c0fe
commit
8371772595
1 changed files with 277 additions and 0 deletions
277
big_o_cheatsheet.md
Normal file
277
big_o_cheatsheet.md
Normal file
|
|
@ -0,0 +1,277 @@
|
||||||
|
# Big O Cheatsheet
|
||||||
|
|
||||||
|
This is just a cheat sheet containing some observations about common for loop
|
||||||
|
patterns taken from Abdul Bari's video series on algorithms.
|
||||||
|
|
||||||
|
## For Loops
|
||||||
|
|
||||||
|
---
|
||||||
|
$$ O(n) $$
|
||||||
|
|
||||||
|
```c
|
||||||
|
for (i = 0; i < n; i++) {} // O(n)
|
||||||
|
for (i = 0; i < n; i = i + 2) {} // = n/2 = O(n)
|
||||||
|
for (i = n; i > 1; i--) {} // O(n)
|
||||||
|
```
|
||||||
|
---
|
||||||
|
|
||||||
|
$$ O(n^2) $$
|
||||||
|
|
||||||
|
```c
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
for (j = 0; j < n; j++) {} // O(n^2)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
$$ O(log_2(n)log_2(p)) $$
|
||||||
|
|
||||||
|
```c
|
||||||
|
for (i = 1; i < n; i = i * 2) {
|
||||||
|
p++; // log_2(n)
|
||||||
|
}
|
||||||
|
for (j = 1; j < p; j = j * 2) {
|
||||||
|
// log_2(p)
|
||||||
|
}
|
||||||
|
// log_2(n) + log_2(p) = O(log_2(n)log_2(p))
|
||||||
|
```
|
||||||
|
---
|
||||||
|
|
||||||
|
$$ O(log_2(n)) $$
|
||||||
|
|
||||||
|
```c
|
||||||
|
for (i = 1; i < n; i = i * 2) {} // O(log_2(n))
|
||||||
|
for (i = n; i > 1; i = i / 2) {} // O(log_2(n))
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
$$ O(log_3(n)) $$
|
||||||
|
|
||||||
|
```c
|
||||||
|
for (i = 1; i < n; i = i * 3) {} // O(log_3(n)
|
||||||
|
```
|
||||||
|
|
||||||
|
## While Loops
|
||||||
|
|
||||||
|
$$ O(n) $$
|
||||||
|
|
||||||
|
```c
|
||||||
|
i = 0;
|
||||||
|
while (i < n) {
|
||||||
|
i++;
|
||||||
|
} // O(n)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
$$ O(log_2(n)) $$
|
||||||
|
|
||||||
|
```c
|
||||||
|
a = 1;
|
||||||
|
while (a < b) {
|
||||||
|
a = a * 2;
|
||||||
|
} // O(log_2(n))
|
||||||
|
|
||||||
|
/* NOTE:
|
||||||
|
a >= b
|
||||||
|
a = 2^k // where k represents unknown value of b
|
||||||
|
2^k >= b // condition where loop stops
|
||||||
|
2^k = b // by making condition where loop stops true...
|
||||||
|
k = log_2(b) we can determine that unknown value b stops when k is equal to log_2 of b
|
||||||
|
which evaluates to: O(log_2(n))
|
||||||
|
*/
|
||||||
|
```
|
||||||
|
|
||||||
|
```c
|
||||||
|
i = n;
|
||||||
|
while (i > 1) {
|
||||||
|
i = i / 2;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
$$ O(\sqrt n) $$
|
||||||
|
|
||||||
|
```c
|
||||||
|
i = 1;
|
||||||
|
k = 1;
|
||||||
|
while (k < n) {
|
||||||
|
k = k + i;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Analyzing the above with some dummy data:
|
||||||
|
|
||||||
|
| i | k |
|
||||||
|
| :- | :------------ |
|
||||||
|
| 1 | 1 |
|
||||||
|
| 2 | 1 + 1 |
|
||||||
|
| 3 | 2 + 2 |
|
||||||
|
| 4 | 2 + 2 + 3 |
|
||||||
|
| 5 | 2 + 2 + 3 + 4 |
|
||||||
|
| m | ...m |
|
||||||
|
|
||||||
|
Which in mathematical notation would be:
|
||||||
|
|
||||||
|
$$ \frac{m(m + 1)}{2} $$
|
||||||
|
|
||||||
|
We can further analyze this like so:
|
||||||
|
|
||||||
|
$$ k \geq n $$
|
||||||
|
|
||||||
|
$$ \frac{m(m + 1)}{2} \geq n $$
|
||||||
|
|
||||||
|
$$ m^2 \geq n $$
|
||||||
|
|
||||||
|
$$ m = \sqrt n $$
|
||||||
|
|
||||||
|
Thusly the big O notation of this is:
|
||||||
|
|
||||||
|
$$ O(\sqrt n) $$
|
||||||
|
|
||||||
|
Note that this is <em>not</em> the same as log_2(n). For an explanation of this,
|
||||||
|
please see
|
||||||
|
[this stack overflow answer](https://stackoverflow.com/questions/42038294/is-complexity-ologn-equivalent-to-osqrtn).
|
||||||
|
According to other sources (GPT), the time complexity of $$ O(\sqrt n) $$
|
||||||
|
|
||||||
|
is often unavoidable when a matrix of values is unsorted.
|
||||||
|
|
||||||
|
## While loops with If Statements
|
||||||
|
|
||||||
|
$$ O(n) $$
|
||||||
|
|
||||||
|
The following demonstrates evaluating the GCD(Greatest Common Divisor) between
|
||||||
|
two numbers:
|
||||||
|
|
||||||
|
```c
|
||||||
|
while (m != n)
|
||||||
|
{
|
||||||
|
if (m > n)
|
||||||
|
m = m - n;
|
||||||
|
else
|
||||||
|
n = n - m;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Let's take a look at an example where both `m` and `n` start off as equal:
|
||||||
|
|
||||||
|
| m | n |
|
||||||
|
| - | - |
|
||||||
|
| 5 | 5 |
|
||||||
|
|
||||||
|
Since they are equal the condition:
|
||||||
|
|
||||||
|
```c
|
||||||
|
while (m != n)
|
||||||
|
```
|
||||||
|
|
||||||
|
Will never execute, thus the amount of execution steps is 0. Let's look at
|
||||||
|
another example:
|
||||||
|
|
||||||
|
| m | n |
|
||||||
|
| -- | - |
|
||||||
|
| 14 | 2 |
|
||||||
|
|
||||||
|
In this case, the condition:
|
||||||
|
|
||||||
|
```c
|
||||||
|
if (m > n)
|
||||||
|
m = m - n;
|
||||||
|
```
|
||||||
|
|
||||||
|
Evaluates to `true` and the value of `m` is equal to `m - n`, replaced with `14
|
||||||
|
|
||||||
|
- 2`, and thusly`m`is equal to`12`. This continually evaluates down the line
|
||||||
|
like so:
|
||||||
|
|
||||||
|
| m | n |
|
||||||
|
| -- | - |
|
||||||
|
| 14 | 2 |
|
||||||
|
| 12 | 2 |
|
||||||
|
| 10 | 2 |
|
||||||
|
| 8 | 2 |
|
||||||
|
| 6 | 2 |
|
||||||
|
| 4 | 2 |
|
||||||
|
| 2 | 2 |
|
||||||
|
|
||||||
|
At which point the loop stops because the condition:
|
||||||
|
|
||||||
|
```c
|
||||||
|
while (m != n)
|
||||||
|
```
|
||||||
|
|
||||||
|
Evaluates to `false`, and the loop ends, resulting in the loop having executed 7
|
||||||
|
times. We add 1 to the amount of times it is executed by nature of the initial
|
||||||
|
loop, and it is 8. This evaluates to
|
||||||
|
|
||||||
|
$$ \frac{16}{2} $$
|
||||||
|
|
||||||
|
or:
|
||||||
|
|
||||||
|
$$ \frac{n}{2} $$
|
||||||
|
|
||||||
|
Which, in big O notation, evaluates to:
|
||||||
|
|
||||||
|
$$ O(n) $$
|
||||||
|
|
||||||
|
The <em>minimum</em> time to execute is at least one time, thusly the minimum
|
||||||
|
time complexity is:
|
||||||
|
|
||||||
|
$$ O(1) $$
|
||||||
|
|
||||||
|
## Best Case vs. Worst Case
|
||||||
|
|
||||||
|
```c
|
||||||
|
void some_algo_test(int n)
|
||||||
|
{
|
||||||
|
if (n < 5)
|
||||||
|
printf("%d\n", n); // 1
|
||||||
|
else
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
|
printf("%d\n", i); // n
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This evaluates in best case to:
|
||||||
|
|
||||||
|
$$ O(1) $$
|
||||||
|
|
||||||
|
This happens when the condition `n < 5` evaluates to `true`, because all it does
|
||||||
|
is print the value of `n` to the console.
|
||||||
|
|
||||||
|
Otherwise, if `n < 5` evaluates to false (i.e. n is a value greater than or
|
||||||
|
equal to 5), then the worst case time complexity occurs, which is:
|
||||||
|
|
||||||
|
$$ O(n) $$
|
||||||
|
|
||||||
|
In essence:
|
||||||
|
|
||||||
|
**BEST CASE**:
|
||||||
|
|
||||||
|
$$ O(1) $$
|
||||||
|
|
||||||
|
**WORST CASE**:
|
||||||
|
|
||||||
|
$$ O(n) $$
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Now let's adjust our function a bit:
|
||||||
|
|
||||||
|
```c
|
||||||
|
void some_algo_test(int n)
|
||||||
|
{
|
||||||
|
if (n < 5)
|
||||||
|
printf("%d\n", n); // 1
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
|
printf("%d\n", i); // n
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Note here, that now, the `for` loop executes regardless of the `if (n < 5)`
|
||||||
|
condition. Thusly the best and worst case scenario become the same:
|
||||||
|
|
||||||
|
$$ O(n) $$
|
||||||
Loading…
Add table
Add a link
Reference in a new issue