Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 24

Understanding Algorithmic Complexity: Best, Worst, and Average Cases

Recommended resources

Hello! Welcome to the next lesson in your journey through algorithms.

In our last session, we focused on comparing different algorithms using Big O notation. We saw that an O(log n) algorithm is generally better than an O(n) one, especially for large inputs. We also got a hint that a single algorithm's performance isn't always fixed. For instance, a linear search can be very fast if the item is at the beginning of a list, but slow if it's at the end.

Today, we will explore this idea in depth. Your learning outcome is to explain the difference between best-case, worst-case, and average-case complexity. Understanding these three scenarios gives you a far more complete and nuanced picture of an algorithm's efficiency, a crucial skill for both building software and succeeding in technical interviews.

Defining the Cases: Best, Worst, and Average

An algorithm's performance can change dramatically based on the specific input it receives, not just the input's size. We categorize this performance into three main "cases".

Let's start with a clear set of definitions.

Worst, Average and Best Case Analysis of Algorithms

This article from GeeksforGeeks provides a concise explanation of the three types of analysis. It will give us a solid foundation for the rest of the lesson.

Read the first three numbered sections: '1. Worst Case Analysis', '2. Best Case Analysis', and '3. Average Case Analysis'. Focus on the definition of each case and the simple linear search example provided for each.

To summarize the key ideas from that reading:

  • Best-Case Complexity: This is the ideal scenario. It describes the performance of an algorithm on the specific input that requires the minimum number of operations. It's the algorithm's "land speed record."
  • Worst-Case Complexity: This is the pessimistic scenario. It describes the performance on the input that requires the maximum number of operations. It provides a performance guarantee: the algorithm will never be slower than its worst-case.
  • Average-Case Complexity: This is the "realistic" scenario. It describes the expected performance of an algorithm averaged over all possible inputs.

Case Study: A Deeper Look at Linear Search

Linear search is the perfect algorithm to explore these concepts because its performance is so clearly tied to the input. Let's analyze it more formally.

1.11 Best Worst and Average Case Analysis

Now, let's dive deeper into the linear search example. Professor Abdul Bari provides a fantastic and detailed analysis of all three cases in this video.

Watch from 02:53 to 08:57. Pay close attention to how he determines the number of operations for the best case, the worst case, and how he calculates the average case by considering all possibilities.

As the video showed, for a list with n elements:

  • Best Case: The target element is at the very first position. The algorithm performs just one comparison. The complexity is O(1).
  • Worst Case: The target element is at the very last position, or not in the list at all. The algorithm must perform n comparisons. The complexity is O(n).
  • Average Case: Assuming the element could be at any position with equal likelihood, we would check, on average, about half the list (n/2 operations). As we know from previous lessons, we drop the constant factor (1/2), so the complexity is still O(n).

Why We Focus on the Worst Case

You might be wondering which case is the most important. In algorithm analysis and technical interviews, the primary focus is almost always on the worst-case complexity.

Let's read a short explanation of why this is the standard practice.

Worst, Average and Best Case Analysis of Algorithms

Worst-case analysis is the most common for very practical reasons. This reading explains why it provides the most useful information for a software engineer.

Read the section titled 'Why is Worst Case Analysis Mostly Used?'. This will clarify the practical importance of understanding an algorithm's upper bound on performance.

The key takeaway is that worst-case analysis gives a performance guarantee. When you choose an algorithm for a critical system, you need to know its behavior under the most strenuous conditions. The best case is often too optimistic to be useful, and the average case can be difficult to calculate and depends on assumptions about the data that may not hold true.


An Important Clarification: Cases vs. Notations

A very common point of confusion is thinking that Big O notation is for the worst case. This is incorrect.

  • Cases (best, worst, average) are about analyzing an algorithm's behavior under different input scenarios.
  • Asymptotic Notations (Big O, Big Omega, Big Theta) are the mathematical tools we use to describe the growth rate of the function that results from that analysis.

You can use Big O to describe the complexity of any case. For example, with linear search:

  • The best-case complexity is O(1).
  • The worst-case complexity is O(n).

This next video clip explains this distinction perfectly.

1.11 Best Worst and Average Case Analysis

Let's watch another clip from Abdul Bari that clarifies the important distinction between 'cases' and 'notations'. Getting this right shows a deep understanding of complexity analysis.

Watch from 08:57 to 11:37. The key insight is that Big O is a tool to describe a function's upper bound, and it can be applied to the cost function derived from any case (best, worst, or average).


When Input Structure Dictates the Case

So far, we've seen how the value we're searching for determines the case in linear search. However, sometimes the entire structure of the input data can create best- and worst-case scenarios.

A great example is searching in a Binary Search Tree (BST). A BST is a data structure where for any node, all values in its left subtree are smaller, and all values in its right subtree are larger. This allows for fast searching.

A balanced Binary Search Tree. Searching in a tree like this is very efficient.

However, what if the tree is constructed from data that is already sorted? You get a "skewed" tree that looks just like a list.

A skewed Binary Search Tree. Searching in this structure is no better than a linear search.

Let's see how this affects performance.

1.11 Best Worst and Average Case Analysis

This video segment explains how searching in a Binary Search Tree can have vastly different performance based on whether the tree is 'balanced' or 'skewed'.

Watch from 13:02 to 18:10. Notice how a balanced tree gives fast search times (O(log n)), similar to the binary search you've seen, while a skewed tree degrades performance significantly to O(n).

This example shows that for some algorithms, the best and worst cases are not just about finding an element in a different position, but can depend on the fundamental structure of the input data.


Your Turn: Analyze an Algorithm

Let's apply what you've learned. Consider the following Python function:

def process_data(data_list):
    """
    If the list has an even number of items, return True immediately.
    If the list has an odd number of items, check if the number 0 is in the list.
    """
    n = len(data_list)

    if n % 2 == 0:
        return True  # Constant time operation
    else:



        # This is essentially a linear search for 0
        for item in data_list:
            if item == 0:
                return True
        return False

Think about these two questions:

  1. What kind of input data_list would trigger the best-case performance? What is its Big O complexity?
  2. What kind of input data_list would trigger the worst-case performance? What is its Big O complexity?

Take a moment to think it through before reading the solution below.

...

Solution:

  • Best Case: The best-case scenario occurs if the input list data_list has an even length (e.g., [1, 2, 3, 4]). In this situation, the if n % 2 == 0: condition is met, and the function returns True immediately after performing only a couple of basic operations (getting length, modulo). The runtime does not depend on the size of the list.

    • Best-Case Complexity: O(1)
  • Worst Case: The worst-case scenario occurs if the list has an odd length and the number 0 is either the last element or not in the list at all (e.g., [1, 3, 5, 7, 9] or [1, 3, 5, 7, 0]). In this situation, the function must execute the else block and iterate through all n items in the list.

    • Worst-Case Complexity: O(n)

Conclusion

Great work! You now have a much more sophisticated way to talk about algorithm efficiency.

Key Takeaways:

  • An algorithm's performance isn't static; it can vary based on the specific input it receives.
  • Best-case complexity is the fastest an algorithm can run (minimum operations).
  • Worst-case complexity is the slowest an algorithm can run (maximum operations). It provides a crucial performance guarantee.
  • Average-case complexity describes the expected performance over all possible inputs.
  • For practical and interview purposes, worst-case analysis is the most important and most commonly used measure.
  • The notation (like Big O) is used to describe the complexity of any of these cases.

Preview of the Next Lesson:
We've spent this entire module analyzing algorithms that are written with loops and simple statements. In our next lesson, we'll shift gears and learn a powerful new technique for writing algorithms: recursion. Recursion is a fundamental concept where a function solves a problem by calling itself on smaller pieces of that same problem. It will open up new ways to think about and solve complex algorithmic challenges.