5 Best Ways to Count the Pairs of Reverse Strings in Python

πŸ’‘ Problem Formulation: This article tackles the challenge of identifying and counting pairs of reverse strings in Python. Imagine you have a list of strings such as ["abc", "cba", "def", "fed"]. Our goal is to write Python programs that will count how many pairs of strings are reverses of each otherβ€”in this case, the pair (“abc”, “cba”) and (“def”, “fed”) make our output count 2.

Method 1: Using a dictionary to store counts

This method involves using a dictionary to count ocurreces of each reverse string. It is efficient because it allows for a linear-time solution, as we do not need to compare each string against every other string in the list.

Here’s an example:

def count_reverse_pairs(str_list):
    counter = {}
    for s in str_list:
        reverse_s = s[::-1]
        counter[reverse_s] = counter.get(reverse_s, 0) + 1
    return sum(count//2 for count in counter.values())

example_list = ["abc", "cba", "def", "fed"]
print(count_reverse_pairs(example_list))

Output: 2

This code snippet defines a function count_reverse_pairs() which takes a list of strings as an argument. It iterates over the strings, stores and counts their reverses in a dictionary, and then sums up half the counts (as each pair is counted twice) to get the total number of unique reverse string pairs.

Method 2: Using a set for membership testing

This method leverages the fast membership testing of a set to find reverse pairs. It is efficient for larger datasets because testing if an element is within a set is generally faster than looking up keys in a dictionary.

Here’s an example:

def count_reverse_pairs_set(str_list):
    reverse_set = set()
    pair_count = 0
    for s in str_list:
        if s[::-1] in reverse_set:
            pair_count += 1
        else:
            reverse_set.add(s)
    return pair_count

example_list = ["abc", "cba", "def", "fed"]
print(count_reverse_pairs_set(example_list))

Output: 2

The function count_reverse_pairs_set() creates a set to track the reverse strings seen so far. As it iterates over the list, it checks if the reverse of the current string has already been seen. If so, it increments the count, otherwise, it adds the string to the set.

Method 3: Brute Force Comparison

In this brute-force approach, each string is compared with every other string to check if they are reverses of each other. While straightforward, this method is less efficient for large datasets due to its quadratic time complexity.

Here’s an example:

def count_reverse_pairs_brute(str_list):
    pair_count = 0
    for i in range(len(str_list)):
        for j in range(i+1, len(str_list)):
            if str_list[i] == str_list[j][::-1]:
                pair_count += 1
    return pair_count

example_list = ["abc", "cba", "def", "fed"]
print(count_reverse_pairs_brute(example_list))

Output: 2

The function count_reverse_pairs_brute() uses two nested loops to compare each string with every other string to find reverse pairs, incrementing the pair_count when a match is found.

Method 4: Sorting and Two-Pointer Technique

The two-pointer technique can be applied after sorting the strings and their reverses. By using two pointers, we can pair the original strings with their potential reverses without comparing each string with every other string.

Here’s an example:

def count_reverse_pairs_two_pointers(str_list):
    sorted_list = sorted(str_list)
    reversed_list = sorted(s[::-1] for s in str_list)
    ptr1, ptr2 = 0, 0
    pair_count = 0
    while ptr1 < len(sorted_list) and ptr2 < len(reversed_list):
        if sorted_list[ptr1] == reversed_list[ptr2]:
            pair_count += 1
            ptr1 += 1
            ptr2 += 1
        elif sorted_list[ptr1] < reversed_list[ptr2]:
            ptr1 += 1
        else:
            ptr2 += 1
    return pair_count

example_list = ["abc", "cba", "def", "fed"]
print(count_reverse_pairs_two_pointers(example_list))

Output: 2

count_reverse_pairs_two_pointers() first sorts the list of strings and separately sorts their reverses. Two pointers are then used to scan through both lists simultaneously to find matching pairs without redundant comparisons.

Bonus One-Liner Method 5: Using List Comprehensions and Counting

This one-liner approach leverages Python’s list comprehensions and the count() method for a concise solution, although it may be less efficient due to multiple calls to count().

Here’s an example:

def count_reverse_pairs_oneliner(str_list):
    return sum(str_list.count(s[::-1]) for s in set(str_list)) // 2

example_list = ["abc", "cba", "def", "fed"]
print(count_reverse_pairs_oneliner(example_list))

Output: 2

The function count_reverse_pairs_oneliner() uses a list comprehension to get the count of each string’s reverse in the list, reducing the sum by half to count each unique pair once.

Summary/Discussion

  • Method 1: Using a Dictionary. Linear time complexity. Efficient for large datasets. Does not provide index of pairs.
  • Method 2: Using a Set. Fast membership test. Good for large datasets. May not be as efficient as a dictionary if count of reverses is needed.
  • Method 3: Brute Force Comparison. Simple and straightforward. Quadratic time complexity. Not recommended for large datasets.
  • Method 4: Sorting and Two-Pointer Technique. Efficient for sorted input. Requires extra space for sorted lists. Complexity depends on the sorting algorithm used.
  • Method 5: One-Liner. Concise code. Potentially multiple passes due to count() method. May not be efficient for large datasets.