String slices in Rust - Time & Space Complexity
Let's see how the time it takes to work with string slices changes as the string gets bigger.
We want to know how fast operations on string slices run when the input grows.
Analyze the time complexity of the following code snippet.
fn first_word(s: &str) -> &str {
for (i, &item) in s.as_bytes().iter().enumerate() {
if item == b' ' {
return &s[0..i];
}
}
&s[..]
}
This code finds the first word in a string slice by looking for the first space.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Looping through each byte of the string slice.
- How many times: Up to once for each byte until a space is found or the string ends.
As the string gets longer, the loop may check more characters before finding a space or finishing.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | Up to 10 checks |
| 100 | Up to 100 checks |
| 1000 | Up to 1000 checks |
Pattern observation: The number of checks grows roughly in a straight line with the string length.
Time Complexity: O(n)
This means the time to find the first word grows directly with the length of the string slice.
[X] Wrong: "Finding the first word always takes the same time no matter the string size."
[OK] Correct: If the first space is near the start, it is fast, but if the string has no spaces or the space is near the end, it takes longer because it checks more characters.
Understanding how string slices work and their time cost helps you write efficient code and explain your choices clearly in real projects or interviews.
"What if we changed the code to find the last word instead of the first? How would the time complexity change?"
Practice
Solution
Step 1: Understand string slice concept
A string slice is a reference to a part of a string, not a new string.Step 2: Compare options
Only A reference to a part of a string without copying it describes a reference without copying, which matches string slices.Final Answer:
A reference to a part of a string without copying it -> Option BQuick Check:
String slice = reference without copy [OK]
- Thinking slices create new strings
- Confusing slices with string modification
- Believing slices are integer types
text?Solution
Step 1: Recall Rust slice syntax
Rust uses &string[start..end] to get a slice from start to end-1.Step 2: Check options
&text[0..4] uses &text[0..4], which correctly slices first 4 chars (indices 0 to 3).Final Answer:
&text[0..4] -> Option AQuick Check:
Slice syntax = &string[start..end] [OK]
- Using method calls like slice() which don't exist
- Using 1-based indexing instead of 0-based
- Using Python-style slicing with colons
let s = String::from("hello world");
let slice = &s[6..11];
println!("{}", slice);Solution
Step 1: Understand slicing indices
The slice &s[6..11] takes characters from index 6 up to 10 (11 excluded).Step 2: Identify substring
In "hello world", index 6 is 'w' and index 10 is 'd', so slice is "world".Final Answer:
world -> Option DQuick Check:
Slice &s[6..11] = "world" [OK]
- Including the end index character
- Confusing start and end indices
- Expecting full string output
let s = String::from("rustacean");
let slice = &s[0..5];
println!("{}", slice);
let invalid_slice = &s[5..15];Solution
Step 1: Check slice ranges
The string "rustacean" has length 9, so valid indices are 0 to 8.Step 2: Analyze invalid slice
The slice &s[5..15] tries to access indices beyond length, causing runtime panic.Final Answer:
The slice &s[5..15] causes a runtime panic due to out-of-bounds -> Option AQuick Check:
Out-of-bounds slice = panic [OK]
- Assuming slices auto-adjust to string length
- Thinking &s[0..5] is invalid syntax
- Ignoring runtime panics from invalid slices
text, how can you safely get a slice of the first n characters without risking a runtime panic if n is larger than the string length?Solution
Step 1: Understand safe slicing
To avoid panic, slice end must not exceed string length.Step 2: Use min to limit slice end
Using n.min(text.len()) ensures slice end is at most string length.Final Answer:
Use &text[0..n.min(text.len())] -> Option CQuick Check:
Safe slice end = min(n, length) [OK]
- Slicing without length check causing panic
- Using unwrap() which can panic if None
- Using inclusive range which is invalid for slices
Ready to prove it?
Pass the test and this pattern moves unknown
