Problem overview
The method getFullNames receives two arrays of strings, firstNames and lastNames. The name at position i in one array belongs with the name at position i in the other. The method returns a List[String] of full names, each made of a first name, one space and a last name.
For firstNames = ["John", "Andy", "Mary"] and lastNames = ["Doe", "Smith", "Johnson"], the result is ["John Doe", "Andy Smith", "Mary Johnson"]. John is at index 0 in the first array and Doe is at index 0 in the second, so they form the first full name, and so on.
Approach
The two arrays are parallel: they line up by index. So the work is one pass over the indices. At each index you read one string from each array, join them with a space and collect the result. You need a place to collect results, and a growable buffer is the natural choice because the number of names is only known at run time, while an array has a fixed size.
Scala's immutable List is the return type, so the buffer is converted to a list at the end.
Step by step
- Create the buffer. Declare
namesas an emptyscala.collection.mutable.ArrayBuffer[String]. Writing the full package path means noimportis needed. - Loop over the indices. Use
for (i <- firstNames.indices). The index is needed because the same position is read from two arrays. - Build one full name. Inside the loop, join
firstNames(i), a single space" "andlastNames(i)with+. The space is a separate string in the middle, so it is easy to forget. - Append it.
names += nameadds one element at the end of the buffer. - Convert and return. After the loop,
names.toListcopies the buffer into an immutableList, which is what the declared return type asks for.
The solution in Scala
class Solution {
def getFullNames(firstNames: Array[String], lastNames: Array[String]): List[String] = {
val names = scala.collection.mutable.ArrayBuffer[String]()
for (i <- firstNames.indices) {
val name = firstNames(i) + " " + lastNames(i)
names += name
}
return names.toList
}
}
Some Scala details behind these lines:
valwith a mutable buffer.val namesmeans the namenamesalways refers to the same buffer. The buffer's contents can still grow, which is whynames += nameis allowed. Reassigningnamesitself would not compile.- Arrays, buffers and lists. An
Arrayis mutable but its size is fixed. AnArrayBuffergrows as you append. AListis immutable. Collecting into a buffer and converting once at the end is a common pattern. - Parentheses on a buffer and on an array.
ArrayBuffer[String]()calls the factory with no arguments, and element access also uses parentheses,firstNames(i).
A shorter alternative
Scala can also pair two collections directly with zip. firstNames.zip(lastNames) produces pairs, and mapping each pair to a joined string gives the same list. The loop version above is what the lesson uses, and it makes the index-based thinking explicit.
Complexity
Time: O(n * m) in the worst case, where n is the number of names and m the length of a name. The loop runs n times, and each pass builds one string by copying its characters. If you treat name length as a small constant, this is simply O(n). Appending to an ArrayBuffer takes constant time on average, and toList is one more pass over the n elements.
Space: O(n). The result holds n strings, and the buffer holds the same n before it is converted.
Edge cases and common mistakes
- Empty arrays. With two empty arrays,
firstNames.indicesis empty, the loop doesn't run, and the method returns an empty list. - Forgetting the space.
firstNames(i) + lastNames(i)gives"JohnDoe". The" "between them makes"John Doe". - Returning the buffer. The declared type is
List[String], and anArrayBufferisn't aList, so the compiler rejectsreturn names. CalltoList. - Arrays of different lengths. The loop follows
firstNames.indices. IflastNameswere shorter,lastNames(i)would throw anArrayIndexOutOfBoundsException. The task gives matching arrays, so no check is needed here. - Order. The result keeps the order of the input, because the loop goes from index 0 upward.
