Insert at Middle Specific Position in DSA Rust - Time & Space Complexity
When we insert an element at a specific middle position in a list, the time it takes depends on how far we need to go to reach that position.
We want to understand how the time grows as the list gets bigger.
Analyze the time complexity of the following code snippet.
fn insert_at_middle(vec: &mut Vec<i32>, pos: usize, val: i32) {
vec.insert(pos, val);
}
This code inserts a value at a given position in a vector, shifting elements after that position.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Shifting elements after the insertion position to the right.
- How many times: Number of elements after the position, which depends on input size and position.
As the list grows, the number of elements to shift grows roughly with the distance from the insertion point to the end.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 5 shifts if inserted in middle |
| 100 | About 50 shifts |
| 1000 | About 500 shifts |
Pattern observation: The number of shifts grows roughly proportional to the size of the list.
Time Complexity: O(n)
This means the time to insert grows linearly with the size of the list because elements after the insertion point must move.
[X] Wrong: "Inserting in the middle is always fast because we just add one element."
[OK] Correct: Actually, elements after the insertion point must shift, so the work depends on how many elements move, not just adding one.
Understanding how insertion time grows helps you explain trade-offs in data structures and shows you can analyze real code performance clearly.
"What if we changed the data structure to a linked list? How would the time complexity for insertion at a middle position change?"
Practice
Solution
Step 1: Understand linked list positions
Positions in a linked list start from 1 at the head. Inserting at a middle position means placing a new node between existing nodes.Step 2: Define insertion at middle
Inserting at a specific middle position means the new node will be placed after the node at position (pos-1) and before the node at position pos.Final Answer:
Adding a new node exactly between two existing nodes at a given position -> Option DQuick Check:
Insert at middle = Add node between nodes [OK]
- Confusing insertion with deletion
- Thinking insertion only happens at start or end
- Ignoring position indexing starting at 1
Solution
Step 1: Traverse to position before insertion
The loop runs from 1 to 2 (pos-1) to reach node at position 2, using mutable references to modify links.Step 2: Insert new node at position 3
Create new node with value 10, set its next to current node's next, then update current's next to new node.Final Answer:
Code snippet in option A correctly inserts at position 3 -> Option AQuick Check:
Traverse to pos-1, link new node next to current next, update current next [OK]
- Using immutable references when mutable needed
- Incorrect loop range causing wrong position
- Not updating links properly causing list break
let mut head = Some(Box::new(Node { val: 1, next: Some(Box::new(Node { val: 2, next: Some(Box::new(Node { val: 3, next: None })) })) }));
let mut current = &mut head;
for _ in 1..1 {
current = &mut current.as_mut().unwrap().next;
}
let new_node = Some(Box::new(Node { val: 99, next: current.as_mut().unwrap().next.take() }));
current.as_mut().unwrap().next = new_node;
// Print list code omitted for brevitySolution
Step 1: Traverse to node at position 1
The loop runs from 1 to 1, which is empty, so no iteration; current points to head node with value 1.Step 2: Insert new node after current
New node with value 99 is created with next pointing to current's next (node with value 2). Then current's next is updated to new node.Final Answer:
1 -> 99 -> 2 -> 3 -> null -> Option AQuick Check:
Insert after position 1 adds 99 between 1 and 2 [OK]
- Miscounting loop iterations causing wrong position
- Not updating next pointers correctly
- Confusing node values and positions
let mut current = &mut head;
for _ in 0..2 {
current = &mut current.as_mut().unwrap().next;
}
let new_node = Some(Box::new(Node { val: 5, next: current.take() }));
*current = new_node;Solution
Step 1: Analyze loop iteration count
The loop runs from 0 to 1 (0..2), so two iterations, moving current two nodes ahead, which is past position 2.Step 2: Understand insertion position
To insert at position 2, current should point to node at position 1 (pos-1). Loop should run once, not twice.Final Answer:
The loop runs too many times, moving current past the insertion point -> Option BQuick Check:
Loop count must be pos-1 to insert correctly [OK]
- Off-by-one error in loop range
- Not using mutable references for insertion
- Incorrectly setting new node's next pointer
Solution
Step 1: Check position against list length
Since position 5 is beyond current length 3, traverse until the last node to insert at the end.Step 2: Insert new node at end
Once at last node, set its next pointer to new node with value 50 and next as None.Final Answer:
Traverse until the end if position exceeds length, then insert at the end -> Option CQuick Check:
Insert at end if position too large [OK]
- Crashing or panicking when position is too large
- Ignoring position and inserting at wrong place
- Not handling None next pointers properly
Ready to prove it?
Pass the test and this pattern moves unknown
