A Quick Guide to Big-O Notation, Memoization, Tabulation, and Sorting Algorithms by Example =========================================================================================== Curating Complexity: A Guide to Big-O Notation ------------------------------------------------------------------------ ### A Quick Guide to Big-O Notation, Memoization, Tabulation, and Sorting Algorithms by Example
***Curating Complexity: A Guide to Big-O Notation*** Medium-article-comp-complex
A Node.js repl by bgoonzreplit.com
- Why is looking at runtime not a reliable method of calculating time complexity? - Not all computers are made equal( some may be stronger and therefore boost our runtime speed ) - How many background processes ran concurrently with our program that was being tested? - We also need to ask if our code remains performant if we increase the size of the input. - The real question we need to answering is: `How does our performance scale?`. ### big ‘O’ notation - Big O Notation is a tool for describing the efficiency of algorithms with respect to the size of the input arguments. - Since we use mathematical functions in Big-O, there are a few big picture ideas that we’ll want to keep in mind: - The function should be defined by the size of the input. - `Smaller` Big O is better (lower time complexity) - Big O is used to describe the worst case scenario. - Big O is simplified to show only its most dominant mathematical term. ### Simplifying Math Terms - We can use the following rules to simplify the our Big O functions: - `Simplify Products` : If the function is a product of many terms, we drop the terms that don't depend on n. - `Simplify Sums` : If the function is a sum of many terms, we drop the non-dominant terms. - `n` : size of the input - `T(f)` : unsimplified math function - `O(f)` : simplified math function. `Putting it all together`
- First we apply the product rule to drop all constants. - Then we apply the sum rule to select the single most dominant term. ------------------------------------------------------------------------ ### Complexity Classes Common Complexity Classes #### There are 7 major classes in Time Complexity
#### `O(1) Constant` > **The algorithm takes roughly the same number of steps for any input size.** #### `O(log(n)) Logarithmic` > **In most cases our hidden base of Logarithmic time is 2, log complexity algorithm’s will typically display ‘halving’ the size of the input (like binary search!)** #### `O(n) Linear` > **Linear algorithm’s will access each item of the input “once”.** ### `O(nlog(n)) Log Linear Time` > **Combination of linear and logarithmic behavior, we will see features from both classes.** > Algorithm’s that are log-linear will use **both recursion AND iteration.** ### `O(nc) Polynomial` > **C is a fixed constant.** ### `O(c^n) Exponential` > **C is now the number of recursive calls made in each stack frame.** > **Algorithm’s with exponential time are VERY SLOW.** ------------------------------------------------------------------------ ### Memoization - Memoization : a design pattern used to reduce the overall number of calculations that can occur in algorithms that use recursive strategies to solve. - MZ stores the results of the sub-problems in some other data structure, so that we can avoid duplicate calculations and only ‘solve’ each problem once. - Two features that comprise memoization: 1. FUNCTION MUST BE RECURSIVE. 2. Our additional Data Structure is usually an object (we refer to it as our memo… or sometimes cache!)
### Memoizing Factorial Our memo object is *mapping* out our arguments of factorial to it’s return value. - Keep in mind we didn’t improve the speed of our algorithm. ### Memoizing Fibonacci
- Our time complexity for Fibonacci goes from O(2^n) to O(n) after applying memoization. ### The Memoization Formula > *Rules:* 1. *Write the unoptimized brute force recursion (make sure it works);* 2. *Add memo object as an additional argument .* 3. *Add a base case condition that returns the stored value if the function’s argument is in the memo.* 4. *Before returning the result of the recursive case, store it in the memo as a value and make the function’s argument it’s key.* #### Things to remember 1. *When solving DP problems with Memoization, it is helpful to draw out the visual tree first.* 2. *When you notice duplicate sub-tree’s that means we can memoize.* ------------------------------------------------------------------------ ### Tabulation #### Tabulation Strategy > Use When: - **The function is iterative and not recursive.** - *The accompanying DS is usually an array.* #### Steps for tabulation - *Create a table array based off the size of the input.* - *Initialize some values in the table to ‘answer’ the trivially small subproblem.* - *Iterate through the array and fill in the remaining entries.* - *Your final answer is usually the last entry in the table.* ------------------------------------------------------------------------ ### Memo and Tab Demo with Fibonacci > *Normal Recursive Fibonacci* function fibonacci(n) { if (n <= 2) return 1; return fibonacci(n - 1) + fibonacci(n - 2); } > *Memoization Fibonacci 1* > *Memoization Fibonacci 2* > *Tabulated Fibonacci* ### Example of Linear Search - *Worst Case Scenario: The term does not even exist in the array.* - *Meaning: If it doesn’t exist then our for loop would run until the end therefore making our time complexity O(n).* ------------------------------------------------------------------------ ### Sorting Algorithms ### Bubble Sort `Time Complexity`: Quadratic O(n^2) - The inner for-loop contributes to O(n), however in a worst case scenario the while loop will need to run n times before bringing all n elements to their final resting spot. `Space Complexity`: O(1) - Bubble Sort will always use the same amount of memory regardless of n.
- The first major sorting algorithm one learns in introductory programming courses. - Gives an intro on how to convert unsorted data into sorted data. > It’s almost never used in production code because: - *It’s not efficient* - *It’s not commonly used* - *There is stigma attached to it* - `Bubbling Up`* : Term that infers that an item is in motion, moving in some direction, and has some final resting destination.* - *Bubble sort, sorts an array of integers by bubbling the largest integer to the top.* - *Worst Case & Best Case are always the same because it makes nested loops.* - *Double for loops are polynomial time complexity or more specifically in this case Quadratic (Big O) of: O(n²)* ### Selection Sort `Time Complexity`: Quadratic O(n^2) - Our outer loop will contribute O(n) while the inner loop will contribute O(n / 2) on average. Because our loops are nested we will get O(n²); `Space Complexity`: O(1) - Selection Sort will always use the same amount of memory regardless of n.
- Selection sort organizes the smallest elements to the start of the array.
Summary of how Selection Sort should work: 1. *Set MIN to location 0* 2. *Search the minimum element in the list.* 3. *Swap with value at location Min* 4. *Increment Min to point to next element.* 5. *Repeat until list is sorted.* ### Insertion Sort `Time Complexity`: Quadratic O(n^2) - Our outer loop will contribute O(n) while the inner loop will contribute O(n / 2) on average. Because our loops are nested we will get O(n²); `Space Complexity`: O(n) - Because we are creating a subArray for each element in the original input, our Space Comlexity becomes linear.
### Merge Sort `Time Complexity`: Log Linear O(nlog(n)) - Since our array gets split in half every single time we contribute O(log(n)). The while loop contained in our helper merge function contributes O(n) therefore our time complexity is O(nlog(n)); `Space Complexity`: O(n) - We are linear O(n) time because we are creating subArrays.
### Example of Merge Sort
- **Merge sort is O(nlog(n)) time.** - *We need a function for merging and a function for sorting.* > Steps: 1. *If there is only one element in the list, it is already sorted; return the array.* 2. *Otherwise, divide the list recursively into two halves until it can no longer be divided.* 3. *Merge the smallest lists into new list in a sorted order.* ### Quick Sort `Time Complexity`: Quadratic O(n^2) - Even though the average time complexity O(nLog(n)), the worst case scenario is always quadratic. `Space Complexity`: O(n) - Our space complexity is linear O(n) because of the partition arrays we create. - QS is another Divide and Conquer strategy. - Some key ideas to keep in mind: - It is easy to sort elements of an array relative to a particular target value. - An array of 0 or 1 elements is already trivially sorted.
### Binary Search `Time Complexity`: Log Time O(log(n)) `Space Complexity`: O(1)
*Recursive Solution* > *Min Max Solution* - *Must be conducted on a sorted array.* - *Binary search is logarithmic time, not exponential b/c n is cut down by two, not growing.* - *Binary Search is part of Divide and Conquer.* ### Insertion Sort - **Works by building a larger and larger sorted region at the left-most end of the array.** > Steps: 1. *If it is the first element, and it is already sorted; return 1.* 2. *Pick next element.* 3. *Compare with all elements in the sorted sub list* 4. *Shift all the elements in the sorted sub list that is greater than the value to be sorted.* 5. *Insert the value* 6. *Repeat until list is sorted.* ### If you found this guide helpful feel free to checkout my GitHub/gists where I host similar content: bgoonz’s gists
Instantly share code, notes, and snippets. Web Developer, Electrical Engineer JavaScript | CSS | Bootstrap | Python |…gist.github.com
bgoonz — Overview
Web Developer, Electrical Engineer JavaScript | CSS | Bootstrap | Python | React | Node.js | Express | Sequelize…github.com
### Or Checkout my personal Resource Site: Web-Dev-Hub
Memoization, Tabulation, and Sorting Algorithms by Example Why is looking at runtime not a reliable method of…bgoonz-blog.netlify.app
### Discover More: Web-Dev-Hub
Memoization, Tabulation, and Sorting Algorithms by Example Why is looking at runtime not a reliable method of…bgoonz-blog.netlify.app
By Bryan Guner on [February 27, 2021](https://medium.com/p/803ff193c522). Canonical link Exported from [Medium](https://medium.com) on September 23, 2021.