Algorithms in Python
Arrays
Data structure that arranges data sequentially in contiguous memory.
- O(1) indexed read
- O(n) random insert/delete
- O(n) lookup
|
|
Sorting
Sorting is the process of rearranging the data in an array, so it is stored in ascending or descending order. Many algorithms for sorting exist, but best complexity is O(nlogn).
|
|
Quicksort
Most common sorting algorithm, it is the built-in implementation in many languages. This algorithm is very suitable for sorting arrays in place.
This technique uses divide and conquer to divide the problem into smaller subproblems by selecting a pivot in the array, and comparing the rest to the pivot.
- O(nlogn) - complexity
|
|
Merge Sort
It is a recursive technique to sort an array, it is very common for parallel sorting because it can partition the data amongst many processes.
This algorithm uses a divide and conquer technique and it works very well because merging already sorted arrays is an O(n) operation.
- O(nlogn) - complexity
|
|
Binary Search
This algorithm improves lookup in lists that are sorted. Generally, looking for a value in a list has O(n) complexity but if the list is already sorted, this technique can do it in O(logn) which is way better.
This technique uses a divide and conquer approach to reduce the space of lookup by skipping irrelevant values.
- O(logn) - complexity
If the item is not found, the item should be in the position anotated with left.
|
|
Two pointers
Technique to traverse an array and find a subarray, it is useful in problems where the naive solution is a double loop. Common problems are related to subarrays or intervals, leveraging a sorted array.
|
|
Intervals
Intervals represent ranges defined by a start and end point, commonly used in scheduling and range problems. A common approach is to sort intervals by start or end times to simplify comparisons and reduce time complexity.
|
|
Linked List
A LinkedList is a data structure that stores elements sequentially, but with nodes scattered randomly in memory. Each node contains a value and a pointer to the next node.
LinkedLists allow efficient insertion/deletion at both ends but do not support indexed access.
|
|
Linked list can be doubly linked and store a pointer to the previous element too.
To iterate through a list, it can check next nodes until it can’t.
|
|
Stack and Queue
These are data structures focused in accessing one end. Stack is a Last-in First-Out type collection, whereas a Queue is a First-in First-out collection. They can be easily implemented but Python already has an implementation.
- O(1) - add or remove from the ends
- O(n) - lookup and indexed access
|
|
Hashmap
Hashmap is a data structure that stores key/value pairs. The values can be efficiently read using the key. It works by hashing the key to store values in a table.
- O(1) - read and write if key is provided
- O(n) - if key is not provided
|
|
Hashset
It’s a special case of hashmap in which the values are of type booleans. This data structure is used to represent sets and generally comes with efficient set algebra operations.
- O(1) - read and write a particular value
- O(n) - most of the set operations
|
|
Ordered Dictionary
Regular dictionaries do not guarantee any particular order when iterating its values. However Ordered Dictionary is a specialized Hashmap that maintains the order of insertion, allowing iteration over the elements in the same sequence in which they were added.
This is achieved by using additional memory to store the insertion order, typically using a linked list.
|
|
Priority Queue
Priority Queue also known as PQ, is a data structure whose objective is to give access to elements based on their assigned priority. The queue is maintains and order of priority such that elements with highest priority (or lowest, depending on the implementation) is always accessed first.
This data structure is commonly implemented with heaps, a special type of binary tree that ensure the highest priority element is efficiently accesible after add or delete operations.
- O(1) - read highest priority element
- O(logn) - insert or delete an element
|
|
Bitmaps
Data structure that efficiently stores bit values in an array, the bits can represent boolean values and the array itself can represent sets. This data structure is less flexible than a set but can be very memory and time efficient.
- O(1) - write and read a binary value
- O(1) - algebra of sets
|
|
Graphs
Data structure that arranges data in terms of its relations.
Tree
Graph data structure that arranges data in hierarchical format and has no cycles. It is often represented as class with recursive pointers to its children.
|
|
Binary Tree
It is an special case of a tree where each node has at most 2 children. This data structure is usually represented with left and right children.
|
|
Depth-First Search
Also known as DFS is algorithm technique to traverse a graph or tree visiting each path in depth, then visiting other paths. It is useful when the problem requires a comparison of final escenarios of each path.
When traversing a tree, the process of the value can occur before visiting the rest of the path or after, this is called pre-order traversal or post-order traversal.
- O(n) - time complexity
- O(h) - memory complexity, where h is the height of the tree
- O(n) - worst case memory complexity, if the tree is skewed
- O(logn) - memory complexity if the tree is balanced
|
|
Breadth-First Search
Also called BFS is a technique to traverse a graph or tree in levels. It can be useful to find the shortest path from the root, but can also be less memory efficient for large paths.
- O(n) - time complexity
|
|
Backtracking
An algorithmic technique to traverse and array and process not only the value but the path taken to the value. This is specially useful modeling decisions as tree and comparing outcomes, for example in games.
|
|
Backtracking can be also implemented in a recursive manner, and sometimes can be a little easier to think of this algorithm this way.
|
|