Problem overview
The function get_full_names receives two vectors of strings, first and last. The name at position i in first belongs with the name at position i in last. The function returns a new vector of full names, each made of the first name, one space and the last name, in the original order.
For first = ["John", "Andy", "Mary"] and last = ["Doe", "Smith", "Johnson"], the result is ["John Doe", "Andy Smith", "Mary Johnson"].
Approach: walk both vectors with one index
The two vectors line up by position, so a single index can step through both at once. At each index you build one string from first[i] and last[i] and add it to a result vector. The result starts empty and grows by one name per iteration, so after the last index it holds every full name in the same order as the inputs.
You can't loop directly over the elements of both vectors with a plain for name in &first, because you would have no way to reach the matching last name. An index solves this: it names the same position in both vectors.
Step by step
- Create the result. Declare
let mut result = Vec::new();. It needsmutbecause you will push into it. You don't write the element type: Rust works out from the laterpushand the return type that it is aVec<String>. - Loop over the indices of
firstwithfor i in 0..first.len(). The range stops beforelen(), so it covers exactly the valid indices. - Build the full name. Inside the loop,
format!("{} {}", first[i], last[i])creates a newString. Each{}is filled by the next argument, and the space between the braces is the single space you need between the names. Bind the result toname. - Push it.
result.push(name)movesnameinto the vector, at the end. - Return
resultonce the loop finishes.
The solution in Rust
impl Solution {
fn get_full_names(first: Vec<String>, last: Vec<String>) -> Vec<String> {
let mut result = Vec::new();
for i in 0..first.len() {
let name = format!("{} {}", first[i], last[i]);
result.push(name);
}
return result;
}
}
The Rust details worth a closer look:
format!versusprintln!. Both use the same template syntax.println!prints the text, whileformat!returns it as a newString.format!only borrows its arguments. Writingfirst[i]inside it doesn't move the string out of the vector. That matters because moving out of an indexedVec<String>isn't allowed:let s = first[0];fails with "cannot move out of index ofVec<String>", becauseStringdoesn't implementCopy. Insideformat!the vector keeps its strings.- Type inference for
Vec::new(). The compiler has no element type when it seesVec::new(). It fills it in from thepushof aStringand from the function's return type. If nothing ever constrained it, you would get an error asking for a type annotation. - Owned strings. The parameters are
Vec<String>, notVec<&str>. Each element owns its text, and the function creates new owned strings for the result. - Pairing with iterators. The idiomatic alternative walks both vectors together with
first.iter().zip(last.iter())and builds the result withmapandcollect. The index loop makes the pairing explicit, which suits this lesson.
Complexity
Let n be the number of names and m the length of the longest name.
Time: O(n * m). The loop runs n times. Each iteration builds a string by copying the two names, which costs time proportional to their lengths. If the names are treated as short and bounded, this is simply O(n).
Space: O(n * m). The result holds n new strings, each about as long as a first and a last name together. Apart from the result, the function uses only the loop variable.
Edge cases and common mistakes
- Empty vectors. Both empty gives an empty result, since the loop never runs.
- Different lengths. The loop runs over
first.len(). Iflastis shorter,last[i]panics with "index out of bounds". The lesson assumes both vectors have the same length. Looping up to the shorter length would be the safe choice for general code. - The space.
format!("{}{}", ...)without a space would giveJohnDoe. The required output has exactly one space between the names and none at the ends. - Moving out of the vector. Writing
let f = first[i];doesn't compile for strings. Borrow with&first[i]or letformat!do it. - Forgetting
mut. Callingpushon an immutable vector is a compile error. - Returning inside the loop. That would stop after the first name. The return goes after the loop.
Testing
first = ["John", "Andy", "Mary"],last = ["Doe", "Smith", "Johnson"]gives["John Doe", "Andy Smith", "Mary Johnson"].first = ["Ada"],last = ["Lovelace"]gives["Ada Lovelace"].- Two empty vectors give an empty vector.
