Problem overview
The method getFullNames(_ names: [String]) receives an array in which first names and last names sit next to each other: the first name at an even index, its last name right after it. It returns a new array with the full names, each first and last name joined by one space.
For ["John", "Doe", "Andy", "Smith", "Mary", "Johnson"] the result is ["John Doe", "Andy Smith", "Mary Johnson"]. Six strings in, three strings out.
Approach
The input is made of pairs, so the loop should move through it two positions at a time instead of one. If i is the index of a first name, then names[i + 1] is its last name. Stepping i through 0, 2, 4, and so on visits each pair exactly once. Build the full name from the two strings, add it to a result array, and return that array.
Step by step
- Create the result array.
var answer = [String]()starts empty. It needsvarbecause it grows in the loop. - Loop over the even indices with
stride(from: 0, to: names.count, by: 2). It produces 0, 2, 4, and stops beforenames.count. The upper bound is excluded, like in a half-open range. - Join the pair.
names[i] + " " + names[i + 1]concatenates the first name, one space and the last name into a constantname. - Append it with
answer.append(name). Appending at the end keeps the output in the same order as the input pairs. - Return after the loop. A
returninside the loop would send back only the first full name.
The solution in Swift
class Solution {
func getFullNames(_ names: [String]) -> [String] {
var answer = [String]()
for i in stride(from: 0, to: names.count, by: 2) {
let name = names[i] + " " + names[i + 1]
answer.append(name)
}
return answer
}
}
Swift details:
strideinstead of a range. Ranges like0..<nalways step by 1.stride(from:to:by:)is the function for other step sizes. Usestride(from:through:by:)when the end value should be included. Swift has no C-stylefor (i = 0; i < n; i += 2)loop.- Arrays of strings.
[String]()creates an empty array of strings, equivalent tovar answer: [String] = []. - The
+operator joins strings, including the space literal in the middle. String interpolation,"\(names[i]) \(names[i + 1])", gives the same result. - Value semantics. The result is a new array. The input is not modified.
to versus through
The difference between the two stride forms is easy to see with six elements. stride(from: 0, to: 6, by: 2) yields 0, 2, 4, while stride(from: 0, through: 6, by: 2) yields 0, 2, 4, 6. Since 6 is not a valid index of a six-element array, the lesson uses to:. The valid indices always stop at names.count - 1, and to: excludes its bound just as 0..<names.count does.
The loop could also run over the pair count instead of the index: for k in 0..<names.count / 2 with names[2 * k] and names[2 * k + 1]. It gives the same result, but with stride the index you use is the index you read, which is simpler to follow.
Complexity
Time: O(n) for n names. The loop runs n / 2 times and builds one string per pair, in time proportional to the characters involved. Space: O(n), because the result holds n / 2 strings.
Edge cases and common mistakes
- Empty input.
stride(from: 0, to: 0, by: 2)produces nothing, so the method returns[]. - An odd number of names. The method assumes complete pairs. With three names, the last pass reads
names[3], which doesn't exist, and the program stops with an index-out-of-range error. The task's input always has pairs. - Stepping by 1. A plain
for i in 0..<names.countwould pair every name with the following one, giving overlapping results like"Doe Andy". - Missing space.
names[i] + names[i + 1]gives"JohnDoe". - Using
to:andthrough:interchangeably. Withthrough: names.countthe last pass would start past the end of the array and crash.
Testing
["John", "Doe", "Andy", "Smith", "Mary", "Johnson"]gives["John Doe", "Andy Smith", "Mary Johnson"].[]gives[].["A", "B"]gives["A B"].
