Taro Logo

Permutation Difference between Two Strings

Easy
Microsoft logo
Microsoft
1 view
Topics:
StringsArrays

You are given two strings s and t such that every character occurs at most once in s and t is a permutation of s.

The permutation difference between s and t is defined as the sum of the absolute difference between the index of the occurrence of each character in s and the index of the occurrence of the same character in t.

Return the permutation difference between s and t.

Example 1:

Input: s = "abc", t = "bac"

Output: 2

Explanation:

For s = "abc" and t = "bac", the permutation difference of s and t is equal to the sum of:

  • The absolute difference between the index of the occurrence of "a" in s and the index of the occurrence of "a" in t.
  • The absolute difference between the index of the occurrence of "b" in s and the index of the occurrence of "b" in t.
  • The absolute difference between the index of the occurrence of "c" in s and the index of the occurrence of "c" in t.

That is, the permutation difference between s and t is equal to |0 - 1| + |1 - 0| + |2 - 2| = 2.

Example 2:

Input: s = "abcde", t = "edbac"

Output: 12

Explanation: The permutation difference between s and t is equal to |0 - 3| + |1 - 2| + |2 - 4| + |3 - 1| + |4 - 0| = 12.

Constraints:

  • 1 <= s.length <= 26
  • Each character occurs at most once in s.
  • t is a permutation of s.
  • s consists only of lowercase English letters.

Solution


Clarifying Questions

When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:

  1. Are the input strings case-sensitive?
  2. Can the input strings contain characters other than lowercase English letters?
  3. What should I return if the strings are not permutations of each other?
  4. Can either of the input strings be empty or null?
  5. Are there any length constraints on the input strings?

Brute Force Solution

Approach

The brute force method involves trying every possible arrangement of the letters in one string to see if it matches the second string after accounting for differences. We generate all possible orderings of the first string's characters. Then, for each ordering, we compare it to the second string.

Here's how the algorithm would work step-by-step:

  1. First, list out every single way you can rearrange the letters of the first string.
  2. Take the first rearrangement you made and carefully compare it, letter by letter, to the second string.
  3. If the rearrangement is an exact match to the second string, you're done! You found a match.
  4. If it's not a match, go to the next rearrangement you created.
  5. Repeat the comparison for every single rearrangement you made, until you find a match or you run out of rearrangements to check.

Code Implementation

def are_strings_permutations_brute_force(first_string, second_string):
    import itertools

    # Generate all possible permutations of the first string
    string_permutations = itertools.permutations(first_string)

    for permutation in string_permutations:
        # Convert the permutation tuple to a string for comparison
        current_permutation_string = ''.join(permutation)

        # Check if the current permutation matches the second string
        if current_permutation_string == second_string:

            # If there's a match, we can return True immediately
            return True

    # If no permutation matches the second string,
    # then the strings aren't permutations of each other
    return False

Big(O) Analysis

Time Complexity
O(n! * n)The brute force approach involves generating all permutations of the first string, which has a length we'll call n. Generating all permutations takes O(n!) time. For each of these n! permutations, we compare it to the second string, which takes O(n) time because we need to compare each character of the permutation with each character of the second string. Therefore, the overall time complexity is O(n! * n).
Space Complexity
O(N!)The brute force method generates all possible permutations of the first string, which requires storing these permutations. Generating all permutations of a string of length N requires storing up to N! permutations, each of which can have length N. Therefore, the space used to store these permutations grows factorially with the size of the input string. Although only one permutation is compared at a time to the second string, all permutations need to exist at some point in memory. Consequently, the space complexity is O(N!).

Optimal Solution

Approach

The most efficient way to solve this problem is to check if the character counts are the same in both strings. We're not interested in the order of characters, only whether both strings have the same number of each character. If they do, then the difference will be 0.

Here's how the algorithm would work step-by-step:

  1. First, count how many times each character appears in the first string.
  2. Then, count how many times each character appears in the second string.
  3. Next, compare the counts for each character in both strings. If the counts are identical for every character, the strings are permutations of each other, and the difference is zero.
  4. If the character counts are not identical, calculate how different they are. For each character find the absolute difference between the counts in both strings.
  5. Finally, add up all of those absolute differences for each character and the result is the permutation difference between the two strings.

Code Implementation

def permutation_difference_between_strings(first_string, second_string):
    first_string_character_counts = {}
    second_string_character_counts = {}

    for character in first_string:
        first_string_character_counts[character] = first_string_character_counts.get(character, 0) + 1

    for character in second_string:
        second_string_character_counts[character] = second_string_character_counts.get(character, 0) + 1

    permutation_difference = 0

    # Iterate through all unique characters and compute difference.
    for character in set(first_string_character_counts.keys()) | set(second_string_character_counts.keys()):
        first_string_count = first_string_character_counts.get(character, 0)
        second_string_count = second_string_character_counts.get(character, 0)

        #Calculate the absolute difference between counts.
        difference = abs(first_string_count - second_string_count)

        permutation_difference += difference

    #The permutation difference is now computed.
    return permutation_difference

Big(O) Analysis

Time Complexity
O(n)Let n be the length of the input strings. Counting character frequencies in the first string takes O(n) time. Counting character frequencies in the second string also takes O(n) time. Finally, comparing the counts and calculating the differences iterates through the alphabet (or the distinct characters found in the strings), which in the worst case is proportional to n. Therefore the total time complexity is O(n) + O(n) + O(n) which simplifies to O(n).
Space Complexity
O(1)The provided solution uses hash maps (or dictionaries) to count character frequencies in both strings. In the worst case, where both strings contain entirely different characters, the size of these hash maps could grow proportionally to the number of unique characters. However, since we're dealing with characters, the number of unique characters is limited by the character set (e.g., ASCII or Unicode). Therefore, the space required for the hash maps is considered constant, independent of the input string length, N. Consequently, the auxiliary space complexity is O(1).

Edge Cases

CaseHow to Handle
One or both input strings are nullThrow IllegalArgumentException or return an error code/null value, depending on the requirements
One or both input strings are emptyReturn 0 if both are empty, or throw IllegalArgumentException/return an error value if only one is empty.
Input strings have different lengthsReturn false or throw an exception, since permutations require equal length.
Input strings are identicalReturn true as identical strings are permutations of each other.
Very long input strings (close to memory limits)Ensure algorithm has efficient space complexity, such as using character counts with constant extra space O(1).
Strings contain unicode charactersThe solution should handle extended ASCII or Unicode characters beyond standard ASCII (consider using a wider character representation like `char32_t` if needed, or carefully choosing data structure).
Strings contain only whitespaceTreat whitespace as any other character, or pre-process strings to remove whitespace, depending on requirements.
Strings contain special charactersThe solution should correctly handle all special characters as their ASCII values will differ and influence count.