This commit is contained in:
Medium Fries 2019-03-15 01:26:26 -07:00
parent fa12687849
commit ea2aa8d2a6
17 changed files with 415 additions and 0 deletions

1
370/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*swp

6
370/notes/1.md Normal file
View File

@ -0,0 +1,6 @@
# lec1
> trees & tree heaps
> also: ilearn still busted but theres a survey to fill out
bin search trees
max/min/heap trees

13
370/notes/2.md Normal file
View File

@ -0,0 +1,13 @@
# Divide and Conquer
Make big problem into smaller problems to solve
## Merge Sort
_yote_
1. find midpoint of list
2. split into two smaller lists
3. keep splitting smaller lists until we have a bunch of 1/2 size lists
4. sort each using the _smaller_ already sorted values against each other into a new sub-list
5. combine and sort each thing

38
370/notes/adj-list.md Normal file
View File

@ -0,0 +1,38 @@
# Adjacency list
Imagine 8 nodes with no connections
To store this data in an _adjacency list_ we need __n__ items to store them.
We'll have 0 __e__dges however so in total our space is (n+e) == (n)
# Adjacency matrix
space: O(n^2)
The convention for notation btw is [x,y] meaning:
* _from x to y_
# Breadth first search
add neighbors of current to queue
go through current's neighbors and add their neighbors to queue
add neighbor's neighbors
keep going until there are no more neighbors to add
go through queue and start popping members out of the queue
# Depth first search
Here we're going deeper into the neighbors
_once we have a starting point_
_available just means that node has a non-visited neighbor_
if available go to a neighbor
if no neighbors available visit
goto 1
# Kahn Sort
# Graph Coloring
When figuring out how many colors we need for the graph, we should note the degree of the graph

32
370/notes/avl-trees.md Normal file
View File

@ -0,0 +1,32 @@
# Self balancing trees aka AVL trees
_time complexity will be in terms of height_
> Height:
distance from nulls after leaves
* impl: _root will typically have the largest height value_
> Balance:
| left_height - right_height |
we can discard the || if we want negative balance vals but it really shouldn't matter
basically: we want the balance for each node to be 1 or 0.
# Self balancing part
We maintain balance through the tree's lifetime as we insert/delete things into the tree
> Insertion/Deletion
* just like BST but we balance starting from the new node
# Restoring balance
There are 4 special cases when dealing with restoring balance:
1. left-left
2. left-right
3. right-left
4. right-right
# Tries

60
370/notes/big-o.md Normal file
View File

@ -0,0 +1,60 @@
# Calculating Big O
Suppose we have the following function
```
func(x):
if cond1
O(n^2)
elif cond2
O(n)
else
O(1)
```
How do we define the _average_ time complexity:
* any input which isn't setup to be _special_
1. linear search which always finds the first elementO(1)
2. linear search that doen't find anything/last elementO(n)
With linear searches: finding an average item in the middle(somwhere) we have to cover:
* x% of the n size list
Since we drop the constants in time complexity expressions we thus end up with O(n).
## Heap Sort
Time Complexity Exercise
* Best:
* Average:
* Worst:
* Space:
## Insertion Sort
Time Complexity Exercise
* Best:
* Already sorted meaning we go through the whole list once
* O(n) - because we'll do the check into our left sub-list but we don't go into it leaving us as constant time spent per item ie c\*n
* Average:
* Pretty close to n^2 just for the sake of
* O(n^2)
* Worst:
* Going through the whole list sorting everything(backwards)
* O(n^2)
* must go through N items for each item
* Space:
# Notation
Time Complexity: O(n)
Space Complexity: OMEGA(n)
Both Complexity: THETA(n)
* such a complexity only exists if O(n) == OMEGA(n)

27
370/notes/complex.md Normal file
View File

@ -0,0 +1,27 @@
# Complexities
yote we talkin about space and time complexity
* Space
How much space this shit takin up
* Time
How fast something it's gonna take
* Both time/space complexity notation
_O(?)_: this notation is used for both space and time complexity
# Scale of Complexity
O(n) we refer as a linear because the higheset order exponent is /1/
The higher the max order of the expression the higher order the overall complexity(duh).
Non-polynomial expressions are just non-polynomial expressions(yote).
In other words the part most people care about is the highest order exponential value in the function/expression, since everything else _will_ be faster than that.
If you want to jam jargon in there go ahead but don't overthink this tbh famalamasham.

3
370/notes/graphs.md Normal file
View File

@ -0,0 +1,3 @@
# Graph
_First of a few pages on graphs_

20
370/notes/sorts.md Normal file
View File

@ -0,0 +1,20 @@
# Cheatsheet for sorts
_using pythonic terminology for these cases_
> Bubble
* take the largest value and buble it to the top/front of the list
> Insertion
> Selection
* take smallest value and drop it to the front
> Merge
* split the hell out of things and sort from the inside out
* goes from side to side
> Heap
* grab max item and append it to a heap
> Quick

16
370/notes/space.md Normal file
View File

@ -0,0 +1,16 @@
# Space complexity
With function calls there is explicit space used.
Implicit space used is about how much work is done to take up space
# Binary recursive search
> Explicit space: O(c)
This is the amount of space taken per call.
We know how much space has to be allocated every call so we can say it would likely be constant
> Implicit: O(log(n))
Because again we will likely take up log(n) times to reach our destination an this comes from our rekked stackspace.

20
370/notes/tries.md Normal file
View File

@ -0,0 +1,20 @@
# Tries - Prefix Trees(syntax trees in disguise)
We can build grammers from symbols where symbols follow a set of rules to build on each other.
Kinda like linguistic sytax trees but, exactly the same.
_Individual syntaxes are combined to build grammers combine to build phrases, etc. etc._
Instead of symbols we use _prefixes_ as our terminology, to build _words_.
Terminally sequenced symbols are denoted by a _leaf_ flag.
# Deletion
We don't actually remove things for trivial cases.
Instead we turn off the leaf flag in the end target node
if we have /bathe/ and /bathes/ as valid phrases and wanted to remaove /bathe/ from our language
* All we have to do is set the /e/ to off as a valid leaf.
If instead we wanted to remove /bathes/ instead we would go to /s/ and then set it to off like before.
* The problem now is that /s/ is hanging and it doesn't have any children so we can remove it entirely
* If a toggled off node has children it means that it necessarily is part of a valid prefix so it can not be removed

57
370/past-midterms/m1.md Normal file
View File

@ -0,0 +1,57 @@
# Practice things
_just going through the practice midterm problems_
1. Identifying sorting algorithms based on progression(_conceptual_)
_bubble sort_: the bigger the value = the bigger the bubble
* compare two values from the start always, bubble up the bigger value
keep compmaring two adjacent values till you get to the end of the list
* kinda like gladiator m&m's
_insertion sort_: we have the left sublist which maintains a ordered state always
* we walk along the unsorted list and try to drop our current value into the currently sorted left-hand sublist.
* Key points:
left hand ordered sublist
_quick sort_: here we push things up to the top immediately where they are then sorted against the left hand sub-list
_heap sort_: make a giant heap(list) and just take the largest/smallest value and prepend/append to the """heap"""
__reponse__: insertion sort
Left side of progression is always sorted while the right isn't
Left side also get progressively larger
2. How you know if a graph is undirected given a matrix(_code_)
_empirically_: check the upper right half of the matrix and check if each coord pair is reflected across the main axis
1. Take a coords pair value(_say True_)
2. Flip the (x,y) so we have /x,y/
3. If the /x,y/ value is the same as (x,y) then those two nodes are bidrectional(i.e. undirected)
The _trick_ here is making sure we don't bother check the divisor axis or below by accident.
3. Binary tree lookup(_code_)
Recursion is the smollest way of doing this so just go with that.
4. Quick sort partition(_code_)
* Just splitting lists again
* Checking for partition results as well
5. Graph traversal(_code_)
DFS/BFS is fair game
List/matrix meme allowed so don't even bother with other trash
6. Emperical Graph Traversal(_conceptual_)
Time complexity of either dfs/bfs will be /v\*e/ or something like that
7. Topological sort(_code_)
big meme matrix/list allowed

Binary file not shown.

View File

53
370/samples/graph.py Executable file
View File

@ -0,0 +1,53 @@
#!/usr/bin/python3
import random
class Node:
def __init__(self, data:int):
self.data = data
# empty list o rama
self.refs = []
def __str__(self):
return f'{self.data}:{self.refs}'
def new_node(data):
"""
Provides a new node for a ref list or a basic s
"""
return Node(data)
def add_node(base, data):
"""
Creates a new node for the base node to hook onto
"""
base.refs.append(new_node(data))
def show_children(node):
"""
LMAO @ your life
"""
print(node.refs)
def populate(node):
"""
Populate our node with some data
"""
for i in range(1,random.randint(2,10)):
new_tmp = new_node(random.randint(0,100))
node.refs.append(new_tmp)
def child_count(node):
print(f'{len(node.refs)}')
if __name__ == "__main__":
root = Node(0)
for i in 'ABCDE':
add_node(root, i)
print(f'Children count of root: {len(root.refs)}')
for i in root.refs:
populate(i)
child_count(i)
print('Root node:')
show_children(root)

37
370/samples/tree.py Normal file
View File

@ -0,0 +1,37 @@
#!/usr/bin/python3
import random # just for some basic population methods
class Node:
def __init__(self,data):
self.data = data
self.children = []
def __str__(self):
return self.data
def __repr__(self):
return f'{self.__str()}:{self.children}'
def new_node(data):
return Node(data)
def add_node(node, lr, val):
node.children.append()
return None
def lvr(root):
"""
Inorder traversal
"""
# left sequence
if root.left is not None:
lvr(root.left)
# visit sequence
print(root.data)
# right sequence
if root.right is not None:
lvr(root.right)
return

32
370/samples/trie.py Normal file
View File

@ -0,0 +1,32 @@
# Syntax tree in disguise
class Node:
def __init__(self, symbol=None, leaf=False, children={}):
# root node doesn't need any actual data
self.symbol = None
self.leaf = leaf
# {key=char : value=Node}
self.children = children
class Trie:
def __init__(self):
# root should contain every letter so that we can pick our thing
root = Node()
#wrapper func
def traverse(self, func, phrase, _node):
# wew lad
def func(_phrase, _node):
return func(phrase)
@traverse
def insert(self, phrase, node):
pass
@traverse
def remove(self, phrase, node):
pass
@traverse
def checkPhrase(self, phrase):
pass