algos1 Flashcards
What is the complexity of quicksort?
O(n log n) in the average case, O(n^2) in the worst case
Why is quicksort O(n^2) in the worst case?
If the input is already sorted and you pick the first item as the pivot every time when you are partitioning, the depth of the call stack will be the same as the number of elements in the list (as you are not really dividing them).. Every time you partition you are going through each element (O(n)), but in the worst case you are partitioning more often before hitting the base case. N.b. in the average case the depth of the stack is log n as you are halving the list each time.
What is a hash table?
A data structure which maps keys to values. When given an input key, this is hashed to give the index of the value, which can then be accessed in O(1) time.
What can go wrong with a hash table?
Collisions. If the hashing algo is not good then many different inputs can get the same index from the hash (collisions). Can use a linked list at that index for the multiple values, but then are forced to search through the linked list in O(n) time to find something
What are some use cases for hash tables?
Preventing duplicates; caching; any time you have to map a key to a value.
What is a hash table’s load factor?
The number of elements / total number of slots in hash table. A load factor of 1 means there are the same number of elements as slots and there is likelihood of collision. To avoid this should expand hash table at load factor of 0.7.
Describe binary search
Given a sorted list and an element e to search for. Get the midpoint of the list and check if e is there. If not, if element in mid is larger than e, reduce the search to the subarray below mid. If element in mid is smaller than e, reduce the search to subarray above mid. This means that every time you don’t find e you are halving the array. Which makes the complexity O(log n).
Describe quicksort
Given a list to sort. Partition the list by picking an element and putting everything smaller to its left and everything larger to its right. Then take the subarray to the left and do the same again, and the subarray to the right and do the same again (recursively call quicksort on the subarrays). Eventually will reach base case where the start of the array is the same as the end of the array, so can return. Once all recursive calls return the array is sorted.
What is breadth first search?
Searching a graph by searching connected nodes, then their connections, then the connections of their connections
What is a graph?
An abstract data type made up of nodes and edges connecting those nodes. Represents a network.
How can you implement a graph?
One way is to use a hash table / dictionary. e.g. { "bob": ["alice", "claire", "dave"], "alice: ["dave", "edgar"] "claire": ["alice"], etc... } In the above, the names are nodes. The list mapped to bob contains bob's neighbours i.e. the nodes bob is connected to.
What is the complexity of breadth first search?
You may be searching your entire network, following each edge. So it is at least O(number of edges). And you are also adding everybody to the queue, which is O(number of vertices). So total is O(V+E)
What are some ways of representing graphs?
Edge lists:
Array of [vertex1, vertex2] objects.
e.g. [ [1, 5], [1, 2], [3, 5] ]
Adjacency matrices [ [0, 1, 0, 0, 0, 0, 1, 0, 1, 0], [1, 0, 0, 0, 1, 0, 1, 0, 0, 1], [0, 0, 0, 0, 1, 0, 1, 0, 0, 0], [0, 0, 0, 0, 1, 1, 0, 0, 1, 0], [0, 1, 1, 1, 0, 1, 0, 0, 0, 1], [0, 0, 0, 1, 1, 0, 0, 0, 0, 0], [1, 1, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 1], [1, 0, 0, 1, 0, 0, 0, 1, 0, 0], [0, 1, 0, 0, 1, 0, 0, 1, 0, 0] ]
Adjacency lists [ [1, 6, 8], [0, 4, 6, 9], [4, 6], [4, 5, 8], [1, 2, 3, 5, 9], [3, 4], [0, 1, 2], [8, 9], [0, 3, 7], [1, 4, 7] ]
What is time for searching for a given edge in different representations of graphs?
edge list: O(E)
adjacency matrix: O(1)
adjacency list: O(degree)
Pseudo code breadth first search
Create a graph (either adjacency matrix, adjacency list or edge list, or as a hashtable)
Create a queue.
Add source node to queue. while queue is not empty: dequeue next node get node's neighbours from graph. for each neighbour that has not been visited: mark as visited check if goal / set predecessor and distance add to queue
So will visit source, then nodes adjacent to source, then nodes adjacent to those nodes etc.
Pseudo code Dijkstra’s algorithm
The goal of DA is to find the shortest path between two nodes in a WEIGHTED, directed (?) graph.
Create a graph (e.g. hashtable mapping nodes to neighbours and the weight between them)
Create a hashtable mappping nodes to cost - i.e the cost to get to that node from the start node.
Create a hashtable mapping nodes to predecessor - their pred on the path from start to finish.
Initialise Costs and Preds for the neighbours of the start node, to contain cost = weight from start to that node and pred = the start node. The rest have cost = infinity and pred = null
Main algo:
Get lowest cost node (LCN)
While lowest cost node != null
For neighbours of lowest cost node:
cost = current cost of neighbour (Costs[n])
new_cost = weight between LCN and neighbour + cost
of LCN
if new_cost < cost, we have found a shorter path to that
node, so make cost of neighbour be new_cost
set Preds[neighbour] to LCN
Add LCN to processed
Get lowest cost node
return Costs, Preds
For finding lowest cost node:
loop through Costs to get node with current lowest cost