Introduction
I was developing a solution for LeetCode today's challenge and decided to write this article to present a Python solution for the problem: 1657. Determine if Two Strings Are Close.
The problem
"Two strings are considered close if you can attain one 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'
(alla's
turn intob's
, and allb's
turn intoa's
).
You can use the operations on either string as many times as necessary.
Given two strings,word1
andword2
, returntrue
ifword1
andword2
are close, andfalse
otherwise."
Check the link in the Introduction section if you want to see the complete problem statement with examples.
Note
Reading the problem statement might lead you to think that you need to implement the two operations to solve the challenge. However there are a few checks you can do instead of starting to implement and execute the operations described in the problem statement.
What to check to solve the problem
The first check is simple and easy: you need to make sure both strings
word1
andword2
have the same length as neither operation would work correctly if they had different lengths.-
The second check is: you need to check if the occurrences of each characters frequency are the same for both strings.
For example,word1 = 'aabbcccc'
andword2 = 'aabcbcaa'
have the same number of occurrences in their character frequencies or, in other words, the same frequency of frequencies:
# word1 # chars frequency: {'c': 4, 'a': 2, 'b': 2} # frequency of frequencies: {2: 2, 4: 1} # word2 # chars frequency: {'a': 4, 'b': 2, 'c': 2} # frequency of frequencies: {2: 2, 4: 1}
The third and last check is that all existing characters in one string must also exist in the other string.
For example,word1 = 'aabbzzzz'
andword2 = 'aabcbcaa'
attend the second check related to the chars frequency. However the strings are not composed of the same characters ('z'
doesn't exist inword2
just as'c'
doesn't exist inword1
) and this is something that none of the operations described in the problem statement can solve.
My first solution
Following is the first solution I wrote to solve the problem:
class Solution:
def closeStrings(self, word1: str, word2: str) -> bool:
dict1 = dict()
dict2 = dict()
if len(word1) == len(word2):
for char in word1:
dict1[char] = dict1.get(char, 0) + 1
for char in word2:
dict2[char] = dict2.get(char, 0) + 1
return sorted(dict1.values()) == sorted(dict2.values()) and set(dict1) == set(dict2)
return False
Cleaning up and optimizing the solution
I did a few optimizations and also cleaned the code a little bit including the Counter
module in my solution and tried to replace the sorted
(which turns the complexity of the code into a nlog(n)) with some other way to improve the runtime complexity.
So I managed to optimize a little bit by rewriting it like this:
from collections import Counter
class Solution:
def closeStrings(self, word1: str, word2: str) -> bool:
dict1 = Counter(word1)
dict2 = Counter(word2)
return (
len(word1) == len(word2) and
Counter(dict1.values()) == Counter(dict2.values()) and
set(dict1) == set(dict2)
)
And if you want to go a little further and try to turn the solution into something even shorter, you can try this:
from collections import Counter
class Solution:
def closeStrings(self, word1: str, word2: str) -> bool:
return (
len(word1) == len(word2) and
Counter(Counter(word1).values()) == Counter(Counter(word2).values()) and
set([*word1]) == set([*word2])
)
Doing those changes improve the code runtime complexity which now is O(n).
Conclusion
To see more details about runtime and space complexity check out this same solution published on LeetCode The Hard Way.
Top comments (0)