𝔩𝔢𝔩𝕠𝔭𝔢𝔷
Connect With Me on LinkedIn

Python Study

Find Three Largest Numbers

Mastering the "Find Three Largest Numbers" Problem in Python

Introduction

Finding the three largest numbers in an array is a common algorithmic challenge that tests one's ability to efficiently process data without relying on built-in sorting functions. This article explores an elegant solution to this problem, demonstrating how to achieve optimal time complexity while maintaining the input array's integrity.

Problem Statement

Given:

  • An array of at least three integers

Objective:

  • Return a sorted array containing the three largest integers from the input array, including duplicates if present

Example:

  • Input: [141, 1, 17, -7, -17, -27, 18, 541, 8, 7, 7]
  • Output: [18, 141, 541]

Assumption:

  • The input array should not be altered directly

Strategy and Hypothesis

To solve this problem efficiently, we'll use three variables to track the largest numbers encountered. By updating these variables as we iterate through the array, we can achieve O(n) time complexity, processing each element only once without sorting.

Implementation

Initial Approach

def findThreeLargestNumbers(array):
    n1 = float("-inf")
    n2 = float("-inf")
    n3 = float("-inf")

    for num in array:
        if num >= n1:
            n3 = n2
            n2 = n1
            n1 = num
        elif num >= n2:
            n3 = n2
            n2 = num
        elif num >= n3:
            n3 = num

    return [n3, n2, n1]

This implementation stores the three largest numbers found in three variables (n1, n2, n3). It iterates through the array once, updating these variables as larger numbers are encountered.

Improved Approach

While the initial approach is efficient, we can improve its readability and maintainability by extracting the update logic into a separate function:

def findThreeLargestNumbers(array):
    threeLargest = [float("-inf")] * 3
    for num in array:
        updateLargest(threeLargest, num)
    return threeLargest

def updateLargest(threeLargest, num):
    if num > threeLargest[2]:
        shiftAndUpdate(threeLargest, num, 2)
    elif num > threeLargest[1]:
        shiftAndUpdate(threeLargest, num, 1)
    elif num > threeLargest[0]:
        shiftAndUpdate(threeLargest, num, 0)

def shiftAndUpdate(array, num, idx):
    for i in range(idx + 1):
        if i == idx:
            array[i] = num
        else:
            array[i] = array[i + 1]

This version improves code organization and makes the logic more explicit, enhancing readability without sacrificing efficiency.

Optimization Analysis

Space Complexity

Both implementations achieve optimal space complexity of O(1), as they use a fixed amount of additional space regardless of the input size.

Time Complexity

The time complexity is O(n), where n is the number of elements in the input array. Since each element is processed once, this solution is highly efficient.

Optimal Space & Time

The current implementation is optimal in terms of both space and time complexity for this specific problem. Further optimization would likely involve trade-offs in readability or flexibility.

Key Takeaways

  1. Efficient solutions often involve tracking key information (in this case, the three largest numbers) without processing the entire dataset multiple times.
  2. Placeholder values (like negative infinity) can simplify edge case handling.
  3. Breaking down complex logic into smaller functions can improve code readability and maintainability without sacrificing performance.
  4. Achieving O(n) time complexity is often possible by processing each element only once and making smart decisions about what information to keep.
  5. Sometimes, the most efficient solution doesn't require sorting or complex data structures but rather clever use of simple variables and logic.

Conclusion

The "Find Three Largest Numbers" problem demonstrates how thoughtful algorithm design can lead to highly efficient solutions. By tracking only the necessary information and processing the data in a single pass, we've created a time- and space-efficient solution. This approach showcases the importance of understanding the problem deeply and thinking creatively about data manipulation. As you encounter similar challenges, remember that sometimes the most elegant solutions come from simplifying the problem and focusing on the essential information needed to solve it.

Previous
Bubble Sort