Slice lifetime basics in Rust - Time & Space Complexity
When working with slices in Rust, it is important to understand how the program's speed changes as the slice size grows.
We want to know how the time to process a slice changes when the slice gets bigger.
Analyze the time complexity of the following code snippet.
fn sum_slice(slice: &[i32]) -> i32 {
let mut total = 0;
for &item in slice {
total += item;
}
total
}
This function adds up all the numbers in a slice and returns the total.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Looping through each element in the slice.
- How many times: Once for every item in the slice.
As the slice gets bigger, the function does more additions, one for each item.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 additions |
| 100 | 100 additions |
| 1000 | 1000 additions |
Pattern observation: The work grows directly with the number of items in the slice.
Time Complexity: O(n)
This means the time to finish grows in a straight line as the slice gets bigger.
[X] Wrong: "The function runs in the same time no matter the slice size."
[OK] Correct: Because the function must look at every item, more items mean more work and more time.
Understanding how loops over slices affect time helps you explain your code clearly and shows you know how programs grow with data size.
"What if we changed the function to only sum the first half of the slice? How would the time complexity change?"
Practice
fn example<'a>(slice: &'a [i32]) {}Solution
Step 1: Understand what a lifetime means in Rust
Lifetimes tell Rust how long a reference is valid to prevent using invalid data.Step 2: Apply this to a slice reference
The lifetime on a slice reference means how long the slice can be safely used.Final Answer:
How long the slice reference is valid in the program -> Option AQuick Check:
Slice lifetime = reference validity [OK]
- Confusing lifetime with size or length
- Thinking lifetime is about element type
- Ignoring lifetime annotations on references
fn process_slice(____) {}Solution
Step 1: Recall lifetime syntax for references
Lifetimes are written as&'abefore the type to indicate the lifetime of the reference.Step 2: Check each option
&'a [i32]correctly places&'abefore the slice type[i32].&[i32]misses lifetime,&'a [i32];has an extra semicolon,&[i32]'aplaces lifetime incorrectly.Final Answer:
&'a [i32] -> Option AQuick Check:
Lifetime syntax = &'a [type] [OK]
- Putting lifetime after the type
- Adding extra semicolons inside parameters
- Omitting lifetime when needed
fn get_first<'a>(slice: &'a [i32]) -> &'a i32 {
&slice[0]
}
fn main() {
let numbers = vec![10, 20, 30];
let first = get_first(&numbers);
println!("{}", first);
}Solution
Step 1: Understand the function behavior
The function returns a reference to the first element of the slice, which is 10.Step 2: Check lifetime correctness and usage
The lifetime 'a ensures the returned reference is valid as long as the input slice is valid. The vector lives long enough, so no error.Final Answer:
10 -> Option BQuick Check:
Returned first element = 10 [OK]
- Thinking lifetime causes compile error here
- Confusing element values
- Expecting runtime panic without reason
fn invalid<'a>() -> &'a [i32] {
let data = vec![1, 2, 3];
&data[..]
}Solution
Step 1: Analyze the function return and data lifetime
The function returns a slice reference with lifetime 'a, but data is created inside the function and dropped when it ends.Step 2: Understand why this causes an error
Returning a reference to local data is invalid because the data won't live long enough, causing a dangling reference.Final Answer:
The function returns a reference to data that will be dropped -> Option CQuick Check:
Returning local reference = error [OK]
- Assuming lifetime annotation fixes local data drop
- Ignoring ownership rules
- Thinking slice syntax is wrong
fn longest_slice<'a>(x: &'a [i32], y: &'a [i32]) -> &____ [i32] {
if x.len() > y.len() { x } else { y }
}Solution
Step 1: Understand the function's return lifetime
The function returns a slice that could come from either input slice, both sharing lifetime 'a.Step 2: Use shared lifetime for safety
The correct lifetime for the return is'a, matching the lifetime of both input slices.Final Answer:
'a -> Option DQuick Check:
Return lifetime = 'a of inputs [OK]
- Choosing only one input lifetime
- Using 'static without reason
- Ignoring lifetime intersection rules
Ready to prove it?
Pass the test and this pattern moves unknown
