DEV Community

Cover image for Problem 15: Longest Common Prefix
Vicente G. Reyes
Vicente G. Reyes

Posted on • Originally published at vicentereyes.org

Problem 15: Longest Common Prefix

Hey everyone! 👋

Today, we're solving a popular string manipulation problem: Longest Common Prefix.

The Problem

The goal is to write a function that finds the longest common prefix among a list of strings.

  • A prefix is a substring that occurs at the beginning of a string.
  • The function should return the longest common string that all words in the list start with.
  • If there is no common prefix, it should return an empty string "".

Examples:

  • longest_common_prefix(['flower', 'flow', 'flight']) → Should return 'fl'
  • longest_common_prefix(['dog', 'racecar', 'car']) → Should return "" (no common prefix)
  • longest_common_prefix(['interspecies', 'interstellar']) → Should return 'inters'

The Solution

Here is the Python implementation:

def longest_common_prefix(strings):
    """
    Finds the longest common prefix among a list of strings.
    """
    # Check for empty or invalid input
    if not strings:
        return ""

    # Set the first string as the initial prefix
    prefix = strings[0]

    # Iterate through the remaining strings
    for s in strings[1:]:
        # Shorten the prefix until it matches the start of the current string
        while not s.startswith(prefix):
            prefix = prefix[:-1]
            # If the prefix becomes empty, there is no common prefix
            if prefix == "":
                return ""

    return prefix

# Test cases
print(longest_common_prefix(['flower', 'flow', 'flight']))      # 'fl'
print(longest_common_prefix(['dog', 'racecar', 'car']))         # ''
print(longest_common_prefix(['interspecies', 'interstellar']))  # 'inters'
Enter fullscreen mode Exit fullscreen mode

Code Breakdown

Let's walk through the code line by line:

  1. def longest_common_prefix(strings):

    • Defines a function named longest_common_prefix that takes a list of words (strings) as input.
  2. if not strings:

    • Checks if the input list is empty or None.
    • If it is empty, we return an empty string "".
    • Note: This is a safer and more Pythonic check than strings is None or strings == 0 limit cases!
  3. prefix = strings[0]

    • Sets our initial assumption: let's assume the entire first string is the common prefix.
  4. for s in strings[1:]:

    • Iterates through each subsequent string (s) in the list.
    • strings[1:] is Python slice notation that means "all elements from index 1 to the end".
  5. while not s.startswith(prefix):

    • Keeps running as long as the current string s doesn't start with our assumed prefix.
    • .startswith() checks if a string begins with the specified prefix.
  6. prefix = prefix[:-1]

    • Removes the last character from the prefix to make it shorter.
    • prefix[:-1] is string slicing that takes all characters except the last one.
  7. if prefix == "":

    • If we've removed all characters from the prefix, it means the current word shares no common letters at the beginning with our initial assumed prefix.
    • We immediately return "" as we know there is no common sequence.
  8. return prefix

    • Once we've successfully compared our prefix against all strings, the remaining shortened string is safely our longest common prefix!

Example Walkthrough

Let's trace the function with longest_common_prefix(['flower', 'flow', 'flight']):

  1. Initialization:
    • Start with prefix = 'flower'
  2. Compare with 'flow' (First iteration):
    • 'flow' doesn't start with 'flower'? True.
    • Remove last char: prefix = 'flowe'
    • 'flow' doesn't start with 'flowe'? True.
    • Remove last char: prefix = 'flow'
    • 'flow' doesn't start with 'flow'? False. Stop while loop.
    • Current prefix is safely 'flow'.
  3. Compare with 'flight' (Second iteration):
    • 'flight' doesn't start with 'flow'? True.
    • Remove last char: prefix = 'flo'
    • 'flight' doesn't start with 'flo'? True.
    • Remove last char: prefix = 'fl'
    • 'flight' doesn't start with 'fl'? False. Stop while loop.
    • Current prefix is safely 'fl'.
  4. Result: Loop completes, return 'fl'. ✅

Now let's try longest_common_prefix(['dog', 'racecar', 'car']):

  1. Initialization:
    • Start with prefix = 'dog'
  2. Compare with 'racecar':
    • 'racecar' doesn't start with 'dog'? True. Shorten to prefix = 'do'
    • 'racecar' doesn't start with 'do'? True. Shorten to prefix = 'd'
    • 'racecar' doesn't start with 'd'? True. Shorten to prefix = ""
  3. Result: Prefix is empty "". Immediate return "". ❌ No common prefix found.

Key Optimizations

This approach relies heavily on Horizontal Matching:

  • Shrinking Search Pattern: Instead of checking letter by letter precisely (vertical scaling index-by-index), we start by assuming the maximum possible prefix and aggressively peel off letters from the end whenever mismatches are found.
  • Early Escape: If the prefix shrinks to an empty string at any point, we completely abort without iterating through the rest of the array strings.

This pattern is highly effective, easy to read, and simple to reason out! 🚀


Happy coding! 💻

Top comments (0)