Algorithms
LinkedList
๐ Quick Reference
| Property | Value |
|---|---|
| Type | Doubly-linked node sequence |
| Access | O(n) - must traverse from head/tail |
| Insert/Delete at Ends | O(1) |
| Insert/Delete at Middle | O(1) with iterator, O(n) to find position |
| Memory | Extra overhead per node (prev + next pointers) |
| Best For | Frequent insertions/deletions at known positions |
One-liner: Doubly-linked list with O(1) add/remove at ends, but O(n) random access.
๐ฎ Interactive Visualizer
Watch how LinkedList manages node connections for insertions and deletions:
Loading visualizer...
Try these operations:
- Add at head/tail - see O(1) pointer updates
- Insert in middle - observe node linking
- Remove a node - watch pointer rewiring
- Traverse the list - see the step-by-step access
๐ง Key Operations
Creating
JAVA(8 lines)CodeLoading syntax highlighter...
Adding Elements
JAVA(8 lines)CodeLoading syntax highlighter...
Accessing
JAVA(7 lines)CodeLoading syntax highlighter...
Removing
JAVA(8 lines)CodeLoading syntax highlighter...
Iteration
JAVA(16 lines)CodeLoading syntax highlighter...
๐ Complexity Analysis
| Operation | Time | Notes |
|---|---|---|
addFirst/Last | O(1) | Just update pointers |
removeFirst/Last | O(1) | Just update pointers |
get(i) | O(n) | Must traverse from head or tail |
add(i, e) | O(n) | Find position + O(1) insert |
remove(i) | O(n) | Find position + O(1) remove |
contains(e) | O(n) | Linear search |
size() | O(1) | Stored as field |
Memory Layout
Head โ [prev|data|next] โท [prev|data|next] โท [prev|data|next] โ Tail nullโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ null Each node: ~24 bytes overhead (object header + 2 references) vs ArrayList: ~4 bytes per element (just the reference)
โ When to Use LinkedList
Good Use Cases
- Queue/Deque operations - frequent add/remove at both ends
- Iterator-based modifications - O(1) insert/delete during iteration
- Large elements - moving pointers is cheaper than copying
- Frequent splicing - merging lists is O(1)
Avoid When
- Random access needed - use
ArrayListinstead - Memory is tight - node overhead is significant
- Cache performance matters - non-contiguous memory
- Small elements - overhead dominates actual data
๐ LinkedList as Queue/Stack
JAVA(16 lines)CodeLoading syntax highlighter...
โ ๏ธ Common Pitfalls
1. Using get() in Loops
JAVA(9 lines)CodeLoading syntax highlighter...
2. Wrong Data Structure Choice
JAVA(7 lines)CodeLoading syntax highlighter...
3. Ignoring ArrayDeque Alternative
JAVA(5 lines)CodeLoading syntax highlighter...
๐ค Interview Tips
Q: When would you use LinkedList over ArrayList?
"When you need frequent insertions/deletions at both ends (as Deque), or when modifying during iteration using ListIterator. In practice, ArrayList is usually better due to cache locality and lower memory overhead.
Q: What's the time complexity of get(n/2)?
"O(n), specifically O(n/2). Java's LinkedList optimizes by starting from the closer end (head or tail), but it's still linear. For index n/2, it traverses n/2 nodes.
Q: How does LinkedList implement List and Deque?
"It's a doubly-linked list where each node has prev/next references. Head and tail references enable O(1) operations at both ends, satisfying Deque. The List interface is satisfied by traversing to any index.
Q: ArrayList vs LinkedList for a queue?
"Neither is ideal. UseArrayDeque- it has O(1) operations at both ends like LinkedList, but with ArrayList's cache locality and lower memory overhead.
๐ Series Navigation
Previous: Part 1: ArrayList
Next: Part 3: HashMap
Visualizer:
LinkedList from @tomaszjarosz/react-visualizers