Problem overview
The method reverseWords(_ input: String) -> String returns the words of input in reverse order, separated by single spaces. A word is a run of non-space characters, and the input has exactly one space between neighbouring words. For "sky is blue" the answer is "blue is sky".
The letters inside each word keep their order. Only the order of the words changes.
Approach: turn the string into an array of words
Strings are awkward to rearrange, but arrays are easy. So the plan has three moves: split the string into an array of words, reverse the array, and join the words back together with a space between them. The single-space guarantee is what makes the split trivial. Splitting on one space gives exactly the words, with no empty pieces to filter out.
Step by step
- Split.
input.components(separatedBy: " ")returns a[String]with one element per word. Store it in avarnamedwords, because the next step changes it. - Reverse in place.
words.reverse()reorders the array itself and returns nothing. That is whywordsmust be avar. - Join.
words.joined(separator: " ")glues the elements into one string with a space between each pair. Return that string.
The solution in Swift
class Solution {
func reverseWords(_ input: String) -> String {
var words = input.components(separatedBy: " ")
words.reverse()
return words.joined(separator: " ")
}
}
The Swift details worth a closer look:
reverse()againstreversed(). On an array,reverse()changes it in place and gives back nothing.reversed()leaves the array alone and returns the reversed elements as a new value.components(separatedBy:)andsplit.components(separatedBy:)comes from Foundation, so a standalone file needsimport Foundationat the top. It returns[String]. The standard library'ssplit(separator: " ")needs no import but returns an array ofSubstringvalues, whichjoined(separator:)also accepts.- The two methods treat empty pieces differently.
components(separatedBy: " ")keeps an empty string wherever two separators touch or the string starts or ends with one.split(separator: " ")drops empty pieces by default. For the lesson's input, with one space between words, the two give the same words. joined(separator:). It is called on the array and takes the separator.
Complexity
Let n be the length of the string.
Time: O(n). Splitting reads every character once, reversing the array moves each word reference once, and joining copies every character once into the result.
Space: O(n). The array of words holds all the characters of the input again, and the joined result is a further copy.
Edge cases and common mistakes
- One word.
"one"splits into a single-element array, reversing it changes nothing, and the result is"one". - Empty string. Splitting
""withcomponents(separatedBy: " ")gives an array with one empty string, so the result is"". - Extra spaces. The lesson guarantees single spaces. With
"a b"(two spaces) the split keeps an empty piece between the words, and the reversal returns"b a", with both spaces preserved. The task would need extra cleanup if the input could look like this. - Reversing the characters instead of the words. Reversing the whole string gives
"eulb si yks", which is not the answer. - Using
letforwords.reverse()changes the array, and the compiler rejects that on a constant.
Testing
"sky is blue"gives"blue is sky"."one"gives"one"."a b"gives"b a"."the quick brown fox"gives"fox brown quick the".
