Data Structures organise and store data. Some examples of it are arrays and trees. Bounded data structures impose a storage limit, whereas unbounded are limitless.
Algorithms describe the steps you have to perform in order to accomplish a specific task. For example, sorting and search algorithms.
- The Big-O notation is a way of expressing the time complexity of an algorithm related to the
nnumber of items it has to process:- O(1): Constant
- O(log n): Logarithmic (base 2)
- O(n): Linear
- O(n log n): n log-star n (base 2)
- O(n²): Quadratic
- When expressing time complexity, you should always refer to the worst case scenario. For example,
if you have an array
[1, 5, 21, -5, 3, 6, 88], and would like to find the time complexity for searching the index of the number21, the appropriate time complexity would be O(n), regardless of whether we know we can find the desired index at the third iteration. - It is common for algorithms to contain small optimisations that slightly reduce the number of
operations related to
nas the algorithm progresses, however, we are not looking at the Big-O notation mathematically, what we want instead is an approximation to evaluate how efficient the algorithm is. - A tip to discover the time complexity is to look at how many loops the algorithm has, for example:
- 1 loop: O(n)
- 1 outer loop with an inner loop: O(n²)
The right way of reading the notation is "O of 1, O of log n", etc
Binary logarithms (log n) are the inverse function of the power of two
n²function. They are commonly used in binary search and related algorithms.
The chart below demonstrates the relation of the n number of elements against the N time needed
by different time complexity expressions:
- A recursive method is a method that calls itself.
- In order to recursion to work properly, you need a condition that ends the recursion. This condition is know as the breaking condition or base case.
- When the recursive call satisfies the base case, one says the recursion starts to unwind.
- However, if no base case is provided, the recursive call stack will grow indefinitely resulting in
a
StackOverflowError. - Usually, an iterative implementation (such as a for loop) runs faster and doesn't use as much memory as recursion. However, sometimes the iterative algorithm isn't as intuitive and as short as the recursive algorithm.
- Lastly, even when you provide a base case, you can face a
StackOverflowErrorif the number of calls is too high. Languages such as Scala support tail recursion which optimises recursive calls, however, Java does not.
