Problem overview
isAnagram(s, t) takes two strings of lowercase letters and returns a Boolean: true when t can be formed by rearranging the letters of s, using every letter exactly once, and false otherwise.
For s = "anagram" and t = "nagaram" the answer is true: both words are made of three a, one g, one m, one n and one r. For s = "rat" and t = "car" the answer is false, since t has a c that s lacks. Each string has between 1 and 50,000 characters.
This lesson sets a budget of O(n log n) time and O(n) extra space for the sorted copies, which suits a sorting solution. Faster ways exist and come in later lessons.
Approach: sort both strings and compare
Two strings are anagrams exactly when they contain the same letters the same number of times. They differ only in the order of those letters. Sorting removes the order: after sorting, every anagram of a word turns into the same sequence.
For "anagram" and "nagaram", both sort to aaagmnr, so the sorted forms are equal. For "rat" and "car", the sorted forms are art and acr, which differ at the second letter, so the strings are not anagrams.
That is the whole algorithm: sort s, sort t, and test the two results for equality. A pair with different lengths needs no special case, because two sequences of different lengths are never equal.
The alternative idea is to count the letters of each string and compare the counts. That runs in linear time and is the subject of a later lesson. Sorting is simpler to write and a good first version.
Step by step
- Sort
s.s.toCharArray()turns the string into aCharArray, andsorted()returns a new list with those characters in ascending order. The original string is untouched. The result goes intosortedS. - Sort
t. The same two calls givesortedT. Both strings get identical treatment, so their sorted forms can be compared directly. - Compare.
sortedS == sortedTistruewhen the two lists have the same items in the same order, and that expression is the function's result.
The solution in Kotlin
class Solution {
fun isAnagram(s: String, t: String): Boolean {
val sortedS = s.toCharArray().sorted()
val sortedT = t.toCharArray().sorted()
return sortedS == sortedT
}
}
Kotlin details worth a look:
sorted()returns aList. On aCharArrayit doesn't sort in place. It builds a newList<Char>, so"anagram".toCharArray().sorted()is the list[a, a, a, g, m, n, r]. The in-place version is calledsort().==on lists compares contents. In Kotlin==callsequals, and for lists that compares item by item. That is exactly what this solution needs.==on arrays does not. TwoCharArrayvalues holding the same letters are not equal under==: forval x = "ab".toCharArray()andval y = "ab".toCharArray(),x == yisfalse, because arrays compare by reference.x.contentEquals(y)istrue. This is the reason the solution compares the lists returned bysorted()rather than sorted arrays.- Equivalent forms.
s.toList().sorted()gives the same list, becausetoList()on a string also produces its characters.
Complexity
Time: O(n log n + m log m), where n and m are the lengths of s and t. Each sort costs O(k log k) for a string of length k, and the equality check is linear. When the lengths are equal, this is O(n log n).
Space: O(n + m). The function holds two sorted lists, one entry per character. The input strings are not modified.
Edge cases and common mistakes
- Different lengths.
"ab"against"abb"returnsfalse, because the sorted lists have different sizes. - Identical strings. A string is an anagram of itself, so
isAnagram("abc", "abc")istrue. - Same letters, different counts.
"aab"and"abb"both containaandbbut sort toaabandabb, so the answer isfalse. Checking only that every letter oftappears inswould wrongly accept it. - Comparing arrays with
==. Returnings.toCharArray().sortedArray() == t.toCharArray().sortedArray()would be wrong even though both sides hold the same letters, because it compares array references. Use the lists, or callcontentEquals. - Expecting the sort to change the string. Strings in Kotlin are immutable. There is no way to sort
sin place, which is why the solution builds separate sorted copies.
Testing
s = "anagram",t = "nagaram"givestrue.s = "rat",t = "car"givesfalse.s = "ab",t = "abb"givesfalse.s = "a",t = "a"givestrue.
