Linked List Fundamentals
Linked List Fundamentals
A linked list is a linear data structure where elements are stored in nodes. Each node contains data and a reference (pointer) to the next node.
Visual Example
[1] → [2] → [3] → [4] → null
Node Structure
class ListNode {
int val;
ListNode next;
ListNode(int val) {
this.val = val;
this.next = null;
}
}
Linked List vs Array
| Feature | Array | Linked List |
|---|---|---|
| Access | O(1) random | O(n) sequential |
| Insert at beginning | O(n) | O(1) |
| Insert at end | O(1) amortized | O(n) |
| Delete | O(n) | O(1) with reference |
| Memory | Contiguous | Non-contiguous |
Common Operations
// Create a linked list: 1 → 2 → 3
ListNode head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
// Traverse
ListNode current = head;
while (current != null) {
System.out.println(current.val);
current = current.next;
}
// Insert at beginning
ListNode newNode = new ListNode(0);
newNode.next = head;
head = newNode;
// Delete a node (given reference)
prev.next = prev.next.next;
When to Use Linked List
- Frequent insertions/deletions at beginning
- Unknown size - dynamic size
- No random access needed
- Implementing stacks, queues, graphs
- LRU Cache implementation
Linked List Problems
Linked List Problems
1. Reverse Linked List (LeetCode 206)
public ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode current = head;
while (current != null) {
ListNode next = current.next;
current.next = prev;
prev = current;
current = next;
}
return prev;
}
// Time: O(n), Space: O(1)
2. Detect Cycle (LeetCode 141)
public boolean hasCycle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) return true;
}
return false;
}
// Time: O(n), Space: O(1)
3. Merge Two Sorted Lists (LeetCode 21)
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
ListNode dummy = new ListNode(0);
ListNode current = dummy;
while (list1 != null && list2 != null) {
if (list1.val <= list2.val) {
current.next = list1;
list1 = list1.next;
} else {
current.next = list2;
list2 = list2.next;
}
current = current.next;
}
current.next = (list1 != null) ? list1 : list2;
return dummy.next;
}
4. Middle of Linked List (LeetCode 876)
public ListNode middleNode(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
Fast/Slow Pointer Pattern
Use two pointers moving at different speeds:
- Cycle detection: If they meet, there's a cycle
- Find middle: Fast reaches end, slow is at middle
- Nth from end: Move fast n steps first, then both move
Interactive Visualization
Linked List Traversal
Practice Problems
Given the head of a singly linked list, reverse the list, and return the reversed list.
Example:
Input: head = [1,2,3,4,5]
Output: [5,4,3,2,1]
Reverse the links between nodes.
Optimal Solution — O(n) time, O(1) space
Iterative with prev pointer
class Solution {
public ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode current = head;
while (current != null) {
ListNode next = current.next;
current.next = prev;
prev = current;
current = next;
}
return prev;
}
}Edge Cases:
- Empty list
- Single node
- Two nodes
Merge two sorted linked lists and return it as a sorted list.
Example:
Input: list1 = [1,2,4], list2 = [1,3,4]
Output: [1,1,2,3,4,4]
Merge by comparing nodes from both lists.
Optimal Solution — O(n + m) time, O(1) space
Dummy node with two pointers
class Solution {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
ListNode dummy = new ListNode(0);
ListNode current = dummy;
while (list1 != null && list2 != null) {
if (list1.val <= list2.val) {
current.next = list1;
list1 = list1.next;
} else {
current.next = list2;
list2 = list2.next;
}
current = current.next;
}
current.next = (list1 != null) ? list1 : list2;
return dummy.next;
}
}Edge Cases:
- One list is empty
- Both lists empty
- Lists of different lengths
Given head, the head of a linked list, determine if the linked list has a cycle in it.
Example:
Input: head = [3,2,0,-4], pos = 1
Output: true
There is a cycle where the tail connects to the 1st node.
Optimal Solution — O(n) time, O(1) space
Floyd's cycle detection with slow/fast pointers
class Solution {
public boolean hasCycle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) return true;
}
return false;
}
}Edge Cases:
- No cycle
- Cycle at head
- Single node with cycle
Given the head of a linked list, remove the nth node from the end of the list and return its head.
Example:
Input: head = [1,2,3,4,5], n = 2
Output: [1,2,3,5]
Remove the 2nd node from the end (node with value 4).
Optimal Solution — O(L) time, O(1) space
Two pointers with dummy node: fast moves n+1 steps ahead
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode fast = dummy, slow = dummy;
for (int i = 0; i <= n; i++) fast = fast.next;
while (fast != null) {
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return dummy.next;
}
}Edge Cases:
- Remove head (n = length)
- Single node list
- Remove last node
Add two numbers represented as linked lists. Each node contains a single digit. Digits are stored in reverse order.
Example:
Input: l1 = [2,4,3], l2 = [5,6,4]
Output: [7,0,8]
342 + 465 = 807.
Optimal Solution — O(max(m,n)) time, O(max(m,n)) space
Traverse both lists, add with carry
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode dummy = new ListNode(0);
ListNode current = dummy;
int carry = 0;
while (l1 != null || l2 != null || carry != 0) {
int sum = carry;
if (l1 != null) { sum += l1.val; l1 = l1.next; }
if (l2 != null) { sum += l2.val; l2 = l2.next; }
carry = sum / 10;
current.next = new ListNode(sum % 10);
current = current.next;
}
return dummy.next;
}
}Edge Cases:
- Different length lists
- Result has extra carry digit
- One list is empty
Quiz
1. What is the time complexity of inserting at the beginning of a linked list?
2. How do you detect a cycle in a linked list?
3. What is the primary purpose of Linked List?
4. What is a common mistake when implementing Linked List?
Flashcards
Question
What is the time complexity of linked list insertion at beginning?
Click to reveal answer
Answer
O(1) - just update the head pointer.
Question
How do you find the middle of a linked list?
Click to reveal answer
Answer
Use slow/fast pointers. When fast reaches end, slow is at middle.
Question
What is Linked List?
Click to reveal answer
Answer
Linked List is a key concept in software engineering.
Question
When to use Linked List?
Click to reveal answer
Answer
Use Linked List when building production systems that require reliability, scalability, and maintainability.
Question
Linked List best practices
Click to reveal answer
Answer
Follow SOLID principles, write clean code, test thoroughly, document decisions, and monitor in production.
Revision Notes
Key Takeaways
- 1.Linked list is dynamic size
- 2.No random access - must traverse
- 3.Fast/slow pointers for cycle and middle
- 4.Use dummy node for edge cases
Interview Tips
- •Always handle null head
- •Use dummy node to simplify edge cases
- •Draw the linked list to visualize changes
Cheat Sheet
Linked List Cheat Sheet
Node: val + next pointer
Insert at beginning: O(1)
Insert at end: O(n)
Delete with reference: O(1)
Fast/Slow pointers: Cycle detection, middle element
Reverse: Three pointers: prev, current, next