sagordondev

Scott Gordon

Posted on October 3, 2021

Permutations

"Given a set of distinct numbers, find all of its permutations."

Just recently I got stuck on this problem and ended up using a brute force technique that was not only inefficient, did not entirely solve the problem.

I found at least two ways to solve this properly (Grokking the Coding Interview: Patterns for Coding Questions .. (n.d.) One way is far superior based on time complexity. Let's begin with the less efficient pattern first:

Subsets Pattern with Time Complexity of O(N*N!)

# subsets_str_perm.py
#   Given a set of distinct letters, find all of its permutations.
# by: Scott Gordon

from collections import deque


def get_permutation(string):
    string_length = len(string)
    result = []
    permutations = deque()
    permutations.append([])
    for current_letter in string:
        # Take all permutations and add current num to make new permutation
        s = len(permutations)
        for _ in range(s):
            old_permutation = permutations.popleft()
            # Create new permutation by adding current num @ every position
            for j in range(len(old_permutation) + 1):
                new_permutation = list(old_permutation)
                new_permutation.insert(j, current_letter)
                if len(new_permutation) == string_length:
                    result.append(new_permutation)
                else:
                    permutations.append(new_permutation)

    return result


def find_permutation(string, pattern):
    permuted_pattern = get_permutation(pattern)
    for substring in permuted_pattern:
        s = "".join(substring)
        if s in string:
            result = True
            break
        else:
            result = False
    return result


def main():
    print("Permutation exist: " + str(find_permutation("oidbcaf", "abc")))
    print("Permutation exist: " + str(find_permutation("odicf", "dc")))
    print("Permutation exist: " + str(find_permutation("bcdxabcdy", "bcdyabcdx")))
    print("Permutation exist: " + str(find_permutation("aaacb", "abc")))


main()

Enter fullscreen mode Exit fullscreen mode

Console Output

Next let's take a look at the more efficient pattern:

Sliding Window Pattern with Time Complexity of O(N)

# sliding_win_str_perm.py
#    Given a set of distinct numbers, find all of its permutations
# by: Scott Gordon


def find_permutation(str1, pattern):
    window_start, matched = 0, 0
    char_frequency = {}
    # Create a HashMap to calculate frequencies of all chars in pattern.
    for chr in pattern:
        if chr not in char_frequency:
            char_frequency[chr] = 0
        char_frequency[chr] += 1

    # Iterate through string, add one char at a time to sliding window.
    for window_end in range(len(str1)):
        right_char = str1[window_end]
        if right_char in char_frequency:
            # If added char matches HashMap char, decrement map frequency. If
            # char frequency zero, complete match.
            char_frequency[right_char] -= 1
            if char_frequency[right_char] == 0:
                matched += 1

        # If num of char matched equal to num of distinct chars in
        # pattern (total chars in HashMap), required permutation
        # achieved.
        if matched == len(char_frequency):
            return True

        # If win size > len of pattern, shrink win to make == pattern size.
        # If outgoing char part of pattern, put back in frequency HashMap.
        if window_end >= len(pattern) - 1:
            left_char = str1[window_start]
            window_start += 1
            if left_char in char_frequency:
                if char_frequency[left_char] == 0:
                    matched -= 1
                char_frequency[left_char] += 1

    return False


def main():
    print("Permutation exist: " + str(find_permutation("oidbcaf", "abc")))
    print("Permutation exist: " + str(find_permutation("odicf", "dc")))
    print("Permutation exist: " + str(find_permutation("bcdxabcdy", "bcdyabcdx")))
    print("Permutation exist: " + str(find_permutation("aaacb", "abc")))


main()
Enter fullscreen mode Exit fullscreen mode

Console Output

So, I went from brute forcing the algorithm in my original context, to solving the problem using the subsets pattern, then to improve upon its time complexity using the sliding window pattern. I would recommend running these patterns and debugging them over and over again if this is challenging, I know I had to.

References:

Grokking the Coding Interview: Patterns for Coding Questions .. (n.d.). www.educative.Io. Retrieved October 3, 2021, from https://www.educative.io/courses/grokking-the-coding-interview

Photo by Jean-Louis Paulin on Unsplash

💖 💪 🙅 🚩
sagordondev
Scott Gordon

Posted on October 3, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Permutations
python Permutations

October 3, 2021