First and Last Occurrence of Element in DSA Rust - Time & Space Complexity
We want to know how long it takes to find the first and last positions of a number in a list.
How does the time needed change when the list gets bigger?
Analyze the time complexity of the following code snippet.
fn first_occurrence(arr: &[i32], target: i32) -> Option {
let mut left = 0;
let mut right = arr.len();
while left < right {
let mid = (left + right) / 2;
if arr[mid] >= target {
right = mid;
} else {
left = mid + 1;
}
}
if left < arr.len() && arr[left] == target {
Some(left)
} else {
None
}
}
fn last_occurrence(arr: &[i32], target: i32) -> Option {
let mut left = 0;
let mut right = arr.len();
while left < right {
let mid = (left + right) / 2;
if arr[mid] <= target {
left = mid + 1;
} else {
right = mid;
}
}
if right > 0 && arr[right - 1] == target {
Some(right - 1)
} else {
None
}
}
This code finds the first and last positions of a target number in a sorted list using a method called binary search.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The while loop that halves the search range each time.
- How many times: The loop runs about log2 of the list size times.
Each time the list size doubles, the number of steps increases by one.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 4 steps |
| 100 | About 7 steps |
| 1000 | About 10 steps |
Pattern observation: The steps grow slowly as the list grows, adding only one step when the list size doubles.
Time Complexity: O(log n)
This means the time to find the first or last occurrence grows slowly, increasing by one step each time the list size doubles.
[X] Wrong: "Since we search twice (first and last), the time is double, so O(2n)."
[OK] Correct: Each search is O(log n), and doing two searches is still O(log n) because constants are ignored in big-O.
Knowing how to find positions quickly in sorted data is a key skill. It shows you understand efficient searching and can handle real-world data problems calmly.
"What if the list was not sorted? How would the time complexity change for finding first and last occurrences?"
Practice
Solution
Step 1: Understand the problem statement
The problem asks to find the first and last positions of a specific element in a list.Step 2: Identify what is required
We need to locate the earliest and latest index where the element appears.Final Answer:
The first and last positions where a given element appears -> Option AQuick Check:
Positions = first and last occurrence [OK]
- Confusing with sum or count of elements
- Looking for max/min values instead
- Ignoring the order of occurrences
target in vector v?Solution
Step 1: Understand Rust iterator methods
Thepositionmethod returns the index of the first element matching the condition.Step 2: Check each option
v.iter().position(|&x| x == target) usespositioncorrectly to find the first occurrence index. v.iter().find(|&&x| x == target) returns an Option<&T>, not index. v.iter().filter(|&&x| x == target).count() counts matches, not index. v.iter().last().position(|&x| x == target) is invalid becauselast()returns an element, not an iterator.Final Answer:
v.iter().position(|&x| x == target) -> Option AQuick Check:
position() returns first index [OK]
- Using find() which returns element, not index
- Using count() which returns number of matches
- Trying to call position() after last() which is invalid
let v = vec![2, 3, 5, 3, 7];
let target = 3;
let first = v.iter().position(|&x| x == target);
let last = v.iter().rposition(|&x| x == target);
println!("[{:?}, {:?}]", first, last);Solution
Step 1: Find first occurrence of 3 in vector
Vector is [2, 3, 5, 3, 7]. The first 3 is at index 1.Step 2: Find last occurrence of 3 in vector
The last 3 is at index 3.Final Answer:
[Some(1), Some(3)] -> Option DQuick Check:
First = 1, Last = 3 [OK]
- Confusing indices of first and last occurrences
- Using wrong iterator methods
- Forgetting that indices start at 0
target in vector v:
let last = v.iter().position(|&x| x == target).unwrap();
println!("{}", last);Solution
Step 1: Understand what position() returns
position() returns the index of the first element matching the condition, not the last.Step 2: Identify correct method for last occurrence
To find the last occurrence, rposition() should be used instead of position().Final Answer:
Using position() finds first, not last occurrence -> Option CQuick Check:
position() = first occurrence, not last [OK]
- Using position() for last occurrence
- Ignoring unwrap() panic possibility
- Thinking iter() can't use position()
v with possible duplicates, which approach efficiently finds the first and last occurrence of target using binary search in Rust?Solution
Step 1: Understand the vector is sorted with duplicates
Binary search can be used to find positions efficiently in sorted data.Step 2: Use two binary searches for first and last occurrence
One binary search finds the first index where target appears, another finds the last index.Final Answer:
Use two binary searches: one for first occurrence, one for last occurrence -> Option BQuick Check:
Binary search twice for first and last [OK]
- Using linear scan on large sorted vector
- Using position() which is linear time
- Trying to find both occurrences in one binary search
Ready to prove it?
Pass the test and this pattern moves unknown
