Problem overview
The function print_stars receives a positive integer n as an i32 and prints a triangle of stars: n lines, where line number i holds exactly i stars. It prints the triangle and returns nothing.
For n = 5 the output is:
*
**
***
****
*****
Every line is the line above it plus one more star. That observation is the whole solution.
Approach: grow one row and print it each time
One way to solve it is to compute, for each line number i, a string of i stars and print it. That works, but the rows have a simpler relationship: row 2 is row 1 with a star added at the end, row 3 is row 2 with a star added, and so on.
So the program keeps a single String that starts empty. On each of the n passes of a loop it appends one star and prints the string. The first pass prints one star, the second prints two, and the nth prints n. Nothing needs to be counted, because the string itself remembers how many stars it holds.
Step by step
- Create the row. Declare
starsas an emptyStringwithString::new(). It needslet mut, because the loop changes it, and Rust variables are immutable unless marked otherwise. - Loop
ntimes. The range0..nexcludesn, so it produces exactlynvalues, one per line. The loop variable is never read, so it is named_. - Add one star to the end of
starswithpush. - Print the row with
println!, still inside the loop and after the push. Each call ends with a newline, so every row lands on its own line.
The order of steps 3 and 4 matters. If the loop printed first and pushed afterwards, the first line would be empty and the last line would be missing.
The solution in Rust
impl Solution {
fn print_stars(n: i32) {
let mut stars = String::new();
for _ in 0..n {
stars.push('*');
println!("{}", stars);
}
}
}
A few Rust details in these lines:
- Why
starsand notstr.stris the name of Rust's string slice type, so a variable calledstarsis the clearer choice. pushtakes achar. Acharis written with single quotes,'*'. Writingstars.push("*")with double quotes is a compile error: the compiler expects acharand finds a&str. To append a whole string slice, usepush_str("**").mutis required. Without it,stars.push('*')fails to compile with "cannot borrowstarsas mutable, as it is not declared as mutable".println!is a macro. The!marks it as one. The{}in its format string is replaced by the next argument, herestars, and a newline is added after the text.- The function returns
(). There is no->in the signature, so nothing is returned. The function's result is its printed output. - Range loops.
0..nis a half-open range ofi32values here, becausenis ani32. Ifnis 0 or negative the range is empty and the body never runs.
Complexity
Time: O(n²). The loop runs n times, but printing row i writes i characters, so the total output is 1 + 2 + ... + n = n(n + 1)/2 characters. Any solution has to print that many characters, so the quadratic cost comes from the size of the output, not from the method.
Space: O(n). The only extra memory is the String, which grows to n characters.
Edge cases and common mistakes
n = 1. The loop runs once and prints a single*.n = 0. The range0..0is empty, so nothing is printed. A negativenbehaves the same way.- Printing after the loop. Only the last row would appear, because the string holds the full row by then.
- Declaring the string inside the loop. A fresh empty string on every pass would print one star on every line.
- Using
print!. Unlikeprintln!, it adds no newline, so all the stars would end up on one line. - Using
"*"withpush. Double quotes make a string slice, andpushwants achar.
Testing
n = 1prints*.n = 3prints*,**and***on three lines.n = 0prints nothing.
