1657. Determine if Two Strings Are Close

1657. Determine if Two Strings Are Close

Problem Solving - Day 62

ยท

6 min read

Hello, reader ๐Ÿ‘‹๐Ÿฝ ! Welcome to day 62 of the series on Problem Solving. Through this series, I aim to pick up at least one question everyday and share my approach for solving it.

Today, I will be picking up LeetCode's daily challenge problem: 1657. Determine if Two Strings Are Close.


๐Ÿค” Problem Statement

  • Two strings are considered close if one string can be attained from the other using the following operations:

    • Operation 1: Swap any two existing characters.

      • For example, abcde -> aecdb
    • Operation 2: Transform every occurrence of one existing character into another existing character, and do the same with the other character.

      • For example, aacabb -> bbcbaa (all a's turn into b's, and all b's turn into a's)
    • The two operations on either string can be used as many times as necessary.

    • Given two strings, word1 and word2, return true if word1 and word2 are close*, and false otherwise.*

    • E.g.:

      • word1 = "abc", word2 = "bca" => true

      • word1 = "cabbba", word2 = "abbccc" => false


๐Ÿ’ฌ Thought Process - Count Occurrences

  • There are two major cases when the strings word1 and word1 can never be equal.

    1. When the length of two strings are different.

      • E.g.: word1 = "a" and word2 = "aa".
    2. When either of the strings have characters that are not present in the other.

      • E.g.: word1 = "caaaaa", word2 = "abbccc"
  • So, our first check will be to equate string lengths. If they are different, we can return false.

  • We should also check if either of the strings have characters that are not part of the other string. This can be easily checked using a hash map or a frequency count array.

    • In the problem description, it is specified that the characters are going to be the smaller case letters.

    • Hence, we can use a boolean array of size 26 and set the flag for any character ch to array[ch - 'a'] = true.

  • Now, in both the arrays we are guaranteed to have same characters. But these characters could have different occurrences.

  • E.g.: word1 = "cabbba", word2 = "abbccc"

    • In word1, there are 2 a, 1 c and 3 b

    • In word2, there are 2 b, 1 a and 3 c

    • Yet, it is possible to get the word2 by using swaps and transformation operations on word1.

  • Another E.g.: word1 = "aabbcc" and word2 = "abcbca".

    • In word1, there are 2 a, 2 c and 2 b

    • In word2, there are 2 b, 2 a and 2 c

    • Yet, it is possible to get the word2 by using swaps and transformation operations on word1.

  • So if you see, we apply only swaps when word1 and word2 have characters that have same occurrences and apply transformation and/ or swaps when we have characters with different occurrences.

  • But look at this example: word1 = "aaabcc" and word2 = "aaaabc"

    • Both the words have:

      • Equal length

      • All characters in word1 appearing in word and vice versa

    • Yet, it is impossible to obtain word2 from word1.

    • Even, if we try to transform a to b or b to c, and do a series of swaps, we will not be able to achieve word2.

    • This is because of difference frequencies:

      • In word1, there are 3 a, 1 b and 2 c

      • In word2, there are 4 a, 1 b and 1 c

    • Unless there was one letter in word1 that occurred 4 times and another letter (apart from b), that occurred once, word1 can never be attained.

  • Hence, this is where the next clue is. If the frequencies (need not be the exact same character) of both words are different, word2 can never be attained from word1.

  • In other words all the characters in word1 need not have strictly the same frequency of the characters in word2.

  • But the frequency count in itself should have occurred in word1 for any character if it occurred for word2.

  • So if there were 2 characters that had frequency 4 in word2, there must be exactly 2 characters (need not be same) in word1 that has frequency 4.

  • Hence we can use two arrays of size 26 of integer type to keep count of number of characters in both the strings.

  • Then we can sort the frequency array for both words and use a single loop to traverse and check if the indices at both array contain the same value.

  • E.g.:

    • word1 = "aabbcc" and word2 = "abcbca"

    • Their frequency array would be as follows:

      • word1Count = [2, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

      • word2Count = [1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

    • After sorting:

      • word1Count = [1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

      • word2Count = [1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

    • At every index, both the count arrays have the same value. If we find any mismatch, we return false immediately.

๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿ’ป Solution - One pass + Count

  • Below is the code for the approach using one pass iteration and count.
class Solution {
    public boolean closeStrings(String word1, String word2) {
        if(word1.length() != word2.length()) return false;

        int n = word1.length();

        int[] frequencyWordOne = new int[26];
        int[] frequencyWordTwo = new int[26];

        for(int i = 0; i<n; i++) {
            char ch = word1.charAt(i);
            frequencyWordOne[ch - 'a']++;
        }

        for(int i = 0; i<n; i++) {
            char ch = word2.charAt(i);
            if(frequencyWordOne[ch - 'a'] == 0) {
                return false;
            }
            frequencyWordTwo[ch - 'a']++;
        }

        Arrays.sort(frequencyWordOne);
        Arrays.sort(frequencyWordTwo);

        for(int i = 0; i<26; i++) {
            if(frequencyWordOne[i] != frequencyWordTwo[i]) {
                return false;
            }
        }

        return true;
    }
}
Time Complexity: O(n)
  - n = length of string
      - Note: since the array sizes are constant (26), the sorting
        is basically done on a constant array with (26 * log 26)
Space Complexity: O(1)
      - Note: The arrays are of fixed size 26 and do not scale as
        input size grows


Conclusion

That's a wrap for today's problem. If you liked my explanation then please do drop a like/ comment. Also, please correct me if I've made any mistakes or if you want me to improve something!

Thank you for reading!