How to determine memory and time complexity of an algorithm?
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
To determine the memory and time complexity of an algorithm, it's essential to understand the resources the algorithm uses in terms of both space and time as it processes data. These complexities give us insights into the algorithm's efficiency and scalability.
Time Complexity
Definition
Time complexity evaluates the amount of computational time that an algorithm takes to complete as a function of the size of the input data, often represented as `n`. The time complexity is usually expressed using Big O notation, such as , , , and . This notation describes the upper bound of an algorithm's runtime performance.
Types of Performance
- Best Case: The minimum time an algorithm takes to complete. It provides an optimistic scenario and is generally less useful.
- Worst Case: The maximum amount of time scheduled for all inputs, representing the long-term performance trend.
- Average Case: It considers all possible inputs, taking their distribution into account, and provides an expected time complexity.
Analyzing Time Complexity
- Identify Basic Operations: Determine the fundamental operations that the algorithm performs multiple times. These are the best indicators of time complexity.
- Calculate Operation Counts: Calculate how many times each basic operation is executed relative to `n`.
- Analyze Loops: Nested loops often lead to multiplicative complexity; for example, a loop within a loop (where each runs independently `n` times) suggests .
- Consider Recursive Calls: Recursion might have a complexity that is harder to analyze directly. Use techniques like the Master Theorem or draw recursion trees for better understanding.
Example
- Basic Operations: Comparisons and assignments
- Complexity: because each element is checked exactly once.
- Fixed Part: The space required independent of input size, such as space for constants and simple variables.
- Variable Part: The space which depends on the input size—such as dynamically allocated memory, stack space, etc.
- Space Complexity: , due to recursive calls adding to the stack.
- Involves average time per operation over a sequence of operations. Dynamic resizing in data structures such as dynamic arrays is an example where amortized analysis is used.
- Beyond Big O, other asymptotic notations are used:
- (Theta): Tight bound
- (Omega): Lower bound
- Sometimes solutions with small constants perform better than due to less overhead, especially for small input sizes.
Related reading
- How to determine simplex time complexity ie Max flow
- How to determine the longest increasing subsequence using dynamic programming?
- How to determine whether a binary tree is complete?
- How to determine whether two circular sectors overlap with each other
- How to determine the learning rate and the variance in a gradient descent algorithm?
- How to display the average of multiple runs on tensorboard
- How to devise this solution to Non-Constructible Change challenge from Algoexpert.io
- How to disable sort in DataGridView?

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.