707. Design Linked List
Problem Description
This problem asks you to implement a custom linked list data structure from scratch. You need to create a class called MyLinkedList
that supports the following operations:
-
MyLinkedList()
: Constructor that initializes an empty linked list. -
get(index)
: Returns the value of the node at the givenindex
position (0-indexed). If the index is invalid (negative or greater than or equal to the list size), return-1
. -
addAtHead(val)
: Inserts a new node with valueval
at the beginning of the linked list. This new node becomes the first node. -
addAtTail(val)
: Appends a new node with valueval
at the end of the linked list. -
addAtIndex(index, val)
: Inserts a new node with valueval
at the specifiedindex
position.- If
index
equals the current length of the list, the node is added at the end - If
index
is greater than the length, no insertion occurs - Otherwise, the new node is inserted before the existing node at that index
- If
-
deleteAtIndex(index)
: Removes the node at the givenindex
position if the index is valid.
The implementation uses a dummy head node approach where a sentinel node is placed before the actual first element. This simplifies insertion and deletion operations at the head of the list. The solution maintains a counter cnt
to track the current number of nodes in the list.
Key implementation details:
- The linked list uses 0-based indexing
- A
ListNode
class is used to represent each node withval
andnext
attributes - The dummy node helps avoid special cases when operating on the head of the list
- All traversal operations start from
dummy.next
(the actual first node)
Intuition
When designing a linked list from scratch, we need to handle several edge cases - particularly operations at the head of the list. Without any special handling, inserting or deleting at position 0 requires different logic than other positions because we need to update the head reference itself.
The key insight is to use a dummy (sentinel) node that always stays at the beginning, before any actual data nodes. This dummy node acts as a permanent anchor point, eliminating special cases:
- Without dummy: Inserting at head requires updating the head reference directly
- With dummy: Inserting at head is just inserting after the dummy node, same as any other insertion
By maintaining a cnt
variable to track the size, we can quickly validate indices without traversing the entire list each time. This allows us to reject invalid operations early.
The solution consolidates logic by making addAtHead
and addAtTail
simply call addAtIndex
with appropriate indices (0 and cnt
respectively). This reduces code duplication and potential bugs.
For traversal operations, we use a simple pattern:
- Start with a reference to either
dummy
(for insertion/deletion) ordummy.next
(for getting values) - Move forward
index
times to reach the desired position - Perform the operation
When inserting at index i
, we need to find the node at position i-1
(the predecessor), which is why we start from dummy
and traverse index
times. The dummy node naturally serves as the predecessor for index 0.
The ListNode(val, pre.next)
constructor pattern elegantly handles insertion by creating a new node that points to what comes after the predecessor, then updating the predecessor to point to this new node.
Learn more about Linked List patterns.
Solution Approach
The implementation uses a singly linked list with a dummy head node pattern. Here's how each component works:
Data Structure:
ListNode
: Each node containsval
(the data) andnext
(pointer to the next node)dummy
: A sentinel node that remains before the first actual elementcnt
: Counter to track the current size of the linked list
Constructor (__init__
):
self.dummy = ListNode() self.cnt = 0
Creates an empty dummy node and initializes the counter to 0.
get(index)
Method:
- First validates if
index
is within bounds[0, cnt-1]
- Starts traversal from
dummy.next
(the first actual node) - Moves forward
index
times to reach the target node - Returns the value at that position or
-1
if invalid
addAtIndex(index, val)
- Core Insertion Logic:
- Validates that
index <= cnt
(can insert at the end whenindex == cnt
) - Finds the predecessor node by starting from
dummy
and movingindex
steps - Creates a new node with
ListNode(val, pre.next)
:- The new node's
next
points to what came after predecessor - Updates predecessor's
next
to point to the new node
- The new node's
- Increments the counter
addAtHead(val)
and addAtTail(val)
:
- Simply delegate to
addAtIndex
:- Head insertion:
addAtIndex(0, val)
- Tail insertion:
addAtIndex(cnt, val)
- Head insertion:
deleteAtIndex(index)
Method:
- Validates that
index < cnt
(must be an existing node) - Finds the predecessor by traversing from
dummy
forindex
steps - Saves reference to the node to be deleted (
t = pre.next
) - Bypasses the node by setting
pre.next = t.next
- Cleans up by setting
t.next = None
(helps garbage collection) - Decrements the counter
Time Complexity:
get
: O(n) where n is the indexaddAtHead
: O(1)addAtTail
: O(n) where n is the list sizeaddAtIndex
: O(n) where n is the indexdeleteAtIndex
: O(n) where n is the index
Space Complexity: O(1) for all operations (not counting the space used by the list itself)
The dummy node pattern elegantly handles edge cases, making the code cleaner and more maintainable by treating all positions uniformly.
Ready to land your dream job?
Unlock your dream job with a 3-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a sequence of operations to see how the dummy node pattern works:
Initial State:
dummy -> None cnt = 0
Operation 1: addAtHead(1)
- Calls
addAtIndex(0, 1)
- Start at
dummy
, traverse 0 steps (stay at dummy) - Create new node with value 1, pointing to
dummy.next
(which is None) - Update
dummy.next
to point to new node - Increment cnt to 1
dummy -> [1] -> None cnt = 1
Operation 2: addAtTail(3)
- Calls
addAtIndex(1, 3)
(since cnt = 1) - Start at
dummy
, traverse 1 step to reach node [1] - Create new node [3] pointing to None (since [1].next is None)
- Update [1].next to point to [3]
- Increment cnt to 2
dummy -> [1] -> [3] -> None cnt = 2
Operation 3: addAtIndex(1, 2)
- Validate: index 1 <= cnt 2 ✓
- Start at
dummy
, traverse 1 step to reach node [1] - Create new node [2] pointing to [1].next (which is [3])
- Update [1].next to point to [2]
- Increment cnt to 3
dummy -> [1] -> [2] -> [3] -> None cnt = 3
Operation 4: get(1)
- Validate: 0 <= 1 < 3 ✓
- Start at
dummy.next
(node [1]), traverse 1 step to reach [2] - Return value: 2
Operation 5: deleteAtIndex(1)
- Validate: 1 < cnt 3 ✓
- Start at
dummy
, traverse 1 step to reach node [1] (predecessor) - Save reference to [2] (the node to delete)
- Update [1].next to point to [2].next (which is [3])
- Clear [2].next and decrement cnt to 2
dummy -> [1] -> [3] -> None cnt = 2
Operation 6: addAtHead(6)
- Calls
addAtIndex(0, 6)
- Start at
dummy
, traverse 0 steps (stay at dummy) - Create new node [6] pointing to dummy.next (which is [1])
- Update dummy.next to point to [6]
- Increment cnt to 3
dummy -> [6] -> [1] -> [3] -> None cnt = 3
Operation 7: get(3)
- Validate: 3 < 3 fails (index out of bounds)
- Return -1
Notice how the dummy node eliminates special cases:
- When inserting at head (index 0), we traverse 0 steps from dummy, making it the predecessor
- The dummy node is never deleted or modified (except its
next
pointer) - All insertions follow the same pattern: find predecessor, insert after it
- This uniform approach makes the code cleaner and less error-prone
Solution Implementation
1class ListNode:
2 """Node class for the linked list"""
3 def __init__(self, val=0, next=None):
4 self.val = val
5 self.next = next
6
7
8class MyLinkedList:
9 """Implementation of a singly linked list with a dummy head node"""
10
11 def __init__(self):
12 """Initialize the linked list with a dummy head and size counter"""
13 self.dummy_head = ListNode() # Dummy head node to simplify operations
14 self.size = 0 # Track the number of nodes in the list
15
16 def get(self, index: int) -> int:
17 """
18 Get the value of the node at the given index.
19 Returns -1 if the index is invalid.
20
21 Args:
22 index: The index of the node to retrieve (0-indexed)
23
24 Returns:
25 The value at the given index, or -1 if index is invalid
26 """
27 # Check if index is valid
28 if index < 0 or index >= self.size:
29 return -1
30
31 # Traverse to the target node
32 current = self.dummy_head.next
33 for _ in range(index):
34 current = current.next
35
36 return current.val
37
38 def addAtHead(self, val: int) -> None:
39 """
40 Add a node with the given value at the head of the list.
41
42 Args:
43 val: The value to add at the head
44 """
45 self.addAtIndex(0, val)
46
47 def addAtTail(self, val: int) -> None:
48 """
49 Add a node with the given value at the tail of the list.
50
51 Args:
52 val: The value to add at the tail
53 """
54 self.addAtIndex(self.size, val)
55
56 def addAtIndex(self, index: int, val: int) -> None:
57 """
58 Add a node with the given value before the node at the given index.
59 If index equals the length of the list, append to the end.
60 If index is greater than the length, do nothing.
61
62 Args:
63 index: The index where the new node should be inserted
64 val: The value of the new node
65 """
66 # If index is invalid, do nothing
67 if index > self.size:
68 return
69
70 # Handle negative index by treating it as 0
71 if index < 0:
72 index = 0
73
74 # Find the predecessor of the insertion point
75 predecessor = self.dummy_head
76 for _ in range(index):
77 predecessor = predecessor.next
78
79 # Insert the new node
80 new_node = ListNode(val, predecessor.next)
81 predecessor.next = new_node
82 self.size += 1
83
84 def deleteAtIndex(self, index: int) -> None:
85 """
86 Delete the node at the given index if it exists.
87
88 Args:
89 index: The index of the node to delete (0-indexed)
90 """
91 # Check if index is valid
92 if index < 0 or index >= self.size:
93 return
94
95 # Find the predecessor of the node to delete
96 predecessor = self.dummy_head
97 for _ in range(index):
98 predecessor = predecessor.next
99
100 # Delete the node
101 node_to_delete = predecessor.next
102 predecessor.next = node_to_delete.next
103 node_to_delete.next = None # Help garbage collection
104 self.size -= 1
105
106
107# Your MyLinkedList object will be instantiated and called as such:
108# obj = MyLinkedList()
109# param_1 = obj.get(index)
110# obj.addAtHead(val)
111# obj.addAtTail(val)
112# obj.addAtIndex(index, val)
113# obj.deleteAtIndex(index)
114
1/**
2 * Implementation of a singly linked list with indexed operations.
3 * Uses a dummy head node to simplify edge cases.
4 */
5class MyLinkedList {
6 // Dummy head node to simplify insertion/deletion at the beginning
7 private ListNode dummyHead;
8 // Track the number of elements in the linked list
9 private int size;
10
11 /**
12 * Internal node class for the linked list
13 */
14 private class ListNode {
15 int val;
16 ListNode next;
17
18 ListNode() {
19 this.val = 0;
20 this.next = null;
21 }
22
23 ListNode(int val) {
24 this.val = val;
25 this.next = null;
26 }
27
28 ListNode(int val, ListNode next) {
29 this.val = val;
30 this.next = next;
31 }
32 }
33
34 /**
35 * Initialize the linked list
36 */
37 public MyLinkedList() {
38 dummyHead = new ListNode();
39 size = 0;
40 }
41
42 /**
43 * Get the value of the index-th node in the linked list
44 * @param index The index of the node to retrieve
45 * @return The value at the given index, or -1 if index is invalid
46 */
47 public int get(int index) {
48 // Check if index is valid
49 if (index < 0 || index >= size) {
50 return -1;
51 }
52
53 // Traverse to the target node
54 ListNode current = dummyHead.next;
55 while (index-- > 0) {
56 current = current.next;
57 }
58
59 return current.val;
60 }
61
62 /**
63 * Add a node with the given value at the head of the linked list
64 * @param val The value to add
65 */
66 public void addAtHead(int val) {
67 addAtIndex(0, val);
68 }
69
70 /**
71 * Add a node with the given value at the tail of the linked list
72 * @param val The value to add
73 */
74 public void addAtTail(int val) {
75 addAtIndex(size, val);
76 }
77
78 /**
79 * Add a node with the given value before the index-th node
80 * @param index The position to insert the new node
81 * @param val The value to insert
82 */
83 public void addAtIndex(int index, int val) {
84 // If index is greater than size, do nothing
85 if (index > size) {
86 return;
87 }
88
89 // If index is negative, insert at head
90 index = Math.max(0, index);
91
92 // Find the predecessor of the node to be inserted
93 ListNode predecessor = dummyHead;
94 while (index-- > 0) {
95 predecessor = predecessor.next;
96 }
97
98 // Insert the new node
99 predecessor.next = new ListNode(val, predecessor.next);
100 size++;
101 }
102
103 /**
104 * Delete the index-th node in the linked list
105 * @param index The index of the node to delete
106 */
107 public void deleteAtIndex(int index) {
108 // Check if index is valid
109 if (index < 0 || index >= size) {
110 return;
111 }
112
113 // Find the predecessor of the node to be deleted
114 ListNode predecessor = dummyHead;
115 while (index-- > 0) {
116 predecessor = predecessor.next;
117 }
118
119 // Delete the node
120 ListNode nodeToDelete = predecessor.next;
121 predecessor.next = nodeToDelete.next;
122 nodeToDelete.next = null; // Help garbage collection
123 size--;
124 }
125}
126
127/**
128 * Your MyLinkedList object will be instantiated and called as such:
129 * MyLinkedList obj = new MyLinkedList();
130 * int param_1 = obj.get(index);
131 * obj.addAtHead(val);
132 * obj.addAtTail(val);
133 * obj.addAtIndex(index,val);
134 * obj.deleteAtIndex(index);
135 */
136
1/**
2 * Definition for singly-linked list node
3 */
4struct ListNode {
5 int val;
6 ListNode* next;
7
8 ListNode() : val(0), next(nullptr) {}
9 ListNode(int x) : val(x), next(nullptr) {}
10 ListNode(int x, ListNode* next) : val(x), next(next) {}
11};
12
13/**
14 * Design implementation of a singly linked list with index-based operations
15 */
16class MyLinkedList {
17private:
18 ListNode* dummyHead; // Dummy head node to simplify edge cases
19 int size; // Current size of the linked list
20
21public:
22 /**
23 * Initialize the linked list
24 */
25 MyLinkedList() {
26 dummyHead = new ListNode();
27 size = 0;
28 }
29
30 /**
31 * Get the value of the index-th node in the linked list
32 * @param index: 0-based index of the node
33 * @return: value at the given index, or -1 if index is invalid
34 */
35 int get(int index) {
36 // Check if index is out of bounds
37 if (index < 0 || index >= size) {
38 return -1;
39 }
40
41 // Traverse to the target node
42 ListNode* current = dummyHead->next;
43 while (index--) {
44 current = current->next;
45 }
46
47 return current->val;
48 }
49
50 /**
51 * Add a node with given value at the head of the linked list
52 * @param val: value to be added
53 */
54 void addAtHead(int val) {
55 addAtIndex(0, val);
56 }
57
58 /**
59 * Append a node with given value to the tail of the linked list
60 * @param val: value to be added
61 */
62 void addAtTail(int val) {
63 addAtIndex(size, val);
64 }
65
66 /**
67 * Add a node with given value before the index-th node
68 * @param index: position where the new node should be inserted
69 * @param val: value of the new node
70 */
71 void addAtIndex(int index, int val) {
72 // If index is greater than size, do nothing
73 if (index > size) {
74 return;
75 }
76
77 // Handle negative index by treating it as 0
78 if (index < 0) {
79 index = 0;
80 }
81
82 // Find the predecessor of the position to insert
83 ListNode* predecessor = dummyHead;
84 while (index-- > 0) {
85 predecessor = predecessor->next;
86 }
87
88 // Insert new node between predecessor and its next node
89 ListNode* newNode = new ListNode(val, predecessor->next);
90 predecessor->next = newNode;
91
92 // Update size
93 ++size;
94 }
95
96 /**
97 * Delete the index-th node in the linked list, if the index is valid
98 * @param index: 0-based index of the node to delete
99 */
100 void deleteAtIndex(int index) {
101 // Check if index is out of bounds
102 if (index < 0 || index >= size) {
103 return;
104 }
105
106 // Find the predecessor of the node to delete
107 ListNode* predecessor = dummyHead;
108 while (index-- > 0) {
109 predecessor = predecessor->next;
110 }
111
112 // Remove the target node
113 ListNode* nodeToDelete = predecessor->next;
114 predecessor->next = nodeToDelete->next;
115
116 // Clean up the deleted node
117 nodeToDelete->next = nullptr;
118 delete nodeToDelete;
119
120 // Update size
121 --size;
122 }
123
124 /**
125 * Destructor to clean up allocated memory
126 */
127 ~MyLinkedList() {
128 ListNode* current = dummyHead;
129 while (current != nullptr) {
130 ListNode* next = current->next;
131 delete current;
132 current = next;
133 }
134 }
135};
136
137/**
138 * Your MyLinkedList object will be instantiated and called as such:
139 * MyLinkedList* obj = new MyLinkedList();
140 * int param_1 = obj->get(index);
141 * obj->addAtHead(val);
142 * obj->addAtTail(val);
143 * obj->addAtIndex(index,val);
144 * obj->deleteAtIndex(index);
145 */
146
1// Node class for the linked list
2class LinkNode {
3 public val: number;
4 public next: LinkNode | null;
5
6 constructor(val: number, next: LinkNode | null = null) {
7 this.val = val;
8 this.next = next;
9 }
10}
11
12// Global variable to store the head of the linked list
13let head: LinkNode | null = null;
14
15/**
16 * Retrieves the value at the specified index in the linked list
17 * @param index - The index of the node to retrieve (0-based)
18 * @returns The value at the index, or -1 if index is invalid
19 */
20function get(index: number): number {
21 // Check if list is empty
22 if (head === null) {
23 return -1;
24 }
25
26 // Traverse to the target index
27 let currentNode = head;
28 let currentIndex = 0;
29
30 while (currentIndex < index) {
31 // Check if we've reached the end of the list
32 if (currentNode.next === null) {
33 return -1;
34 }
35 currentNode = currentNode.next;
36 currentIndex++;
37 }
38
39 return currentNode.val;
40}
41
42/**
43 * Adds a node with the given value at the head of the linked list
44 * @param val - The value to add
45 */
46function addAtHead(val: number): void {
47 // Create new node pointing to current head
48 head = new LinkNode(val, head);
49}
50
51/**
52 * Adds a node with the given value at the tail of the linked list
53 * @param val - The value to add
54 */
55function addAtTail(val: number): void {
56 const newNode = new LinkNode(val);
57
58 // If list is empty, new node becomes head
59 if (head === null) {
60 head = newNode;
61 return;
62 }
63
64 // Traverse to the last node
65 let currentNode = head;
66 while (currentNode.next !== null) {
67 currentNode = currentNode.next;
68 }
69
70 // Add new node at the end
71 currentNode.next = newNode;
72}
73
74/**
75 * Adds a node with the given value at the specified index
76 * @param index - The index where the node should be inserted
77 * @param val - The value to add
78 */
79function addAtIndex(index: number, val: number): void {
80 // If index is 0 or negative, add at head
81 if (index <= 0) {
82 addAtHead(val);
83 return;
84 }
85
86 // Create dummy node to simplify insertion logic
87 const dummyNode = new LinkNode(0, head);
88 let currentNode = dummyNode;
89 let currentIndex = 0;
90
91 // Traverse to the node before the insertion point
92 while (currentIndex < index) {
93 // If we reach the end before the index, do nothing
94 if (currentNode.next === null) {
95 return;
96 }
97 currentNode = currentNode.next;
98 currentIndex++;
99 }
100
101 // Insert new node at the target position
102 currentNode.next = new LinkNode(val, currentNode.next);
103
104 // Update head if necessary (though it shouldn't change in this case)
105 head = dummyNode.next;
106}
107
108/**
109 * Deletes the node at the specified index
110 * @param index - The index of the node to delete
111 */
112function deleteAtIndex(index: number): void {
113 // Handle deletion at head
114 if (index === 0) {
115 if (head !== null) {
116 head = head.next;
117 }
118 return;
119 }
120
121 // Create dummy node to simplify deletion logic
122 const dummyNode = new LinkNode(0, head);
123 let currentNode = dummyNode;
124 let currentIndex = 0;
125
126 // Traverse to the node before the deletion point
127 while (currentIndex < index) {
128 // If we reach the end before the index, do nothing
129 if (currentNode.next === null) {
130 return;
131 }
132 currentNode = currentNode.next;
133 currentIndex++;
134 }
135
136 // Delete the target node by skipping it
137 if (currentNode.next !== null) {
138 currentNode.next = currentNode.next.next;
139 }
140
141 // Update head (though it shouldn't change for index > 0)
142 head = dummyNode.next;
143}
144
Time and Space Complexity
Time Complexity:
__init__()
:O(1)
- Simply initializes a dummy node and counterget(index)
:O(n)
- Traverses from the dummy node to the index position, wheren
is the index valueaddAtHead(val)
:O(1)
- CallsaddAtIndex(0, val)
which only needs to traverse 0 nodesaddAtTail(val)
:O(n)
- CallsaddAtIndex(self.cnt, val)
which traversesn
nodes wheren
is the length of the listaddAtIndex(index, val)
:O(index)
orO(n)
- Traverses from dummy node to the index position, worst case isO(n)
when inserting at taildeleteAtIndex(index)
:O(index)
orO(n)
- Traverses from dummy node to the index position, worst case isO(n)
when deleting the last element
Space Complexity:
__init__()
:O(1)
- Only creates one dummy nodeget(index)
:O(1)
- Uses only a single pointer variable for traversaladdAtHead(val)
:O(1)
- Creates one new nodeaddAtTail(val)
:O(1)
- Creates one new nodeaddAtIndex(index, val)
:O(1)
- Creates one new node and uses a pointer for traversaldeleteAtIndex(index)
:O(1)
- Uses two pointer variables for traversal and deletion- Overall space complexity for the data structure:
O(n)
wheren
is the number of elements stored in the linked list
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Off-by-One Errors in Index Traversal
One of the most common mistakes is incorrectly calculating how many steps to traverse when finding a node or its predecessor.
Pitfall Example:
# Incorrect: Traversing to find the node at index
def get(self, index: int) -> int:
current = self.dummy_head # Wrong! Should start from dummy_head.next
for _ in range(index):
current = current.next
return current.val
Why it's wrong: Starting from dummy_head
instead of dummy_head.next
means you're including the dummy node in your traversal, causing you to return the value one position before the intended index.
Correct Approach:
def get(self, index: int) -> int:
current = self.dummy_head.next # Start from the first actual node
for _ in range(index):
current = current.next
return current.val
2. Confusion Between Finding Node vs. Finding Predecessor
Different operations require different traversal targets, which often leads to confusion.
Pitfall Example:
# Incorrect: Using the same traversal logic for all operations
def deleteAtIndex(self, index: int) -> None:
current = self.dummy_head.next # Wrong for deletion!
for _ in range(index):
current = current.next
# Now current is the node to delete, but we need its predecessor!
Why it's wrong: For deletion and insertion, you need the predecessor node to modify its next
pointer. For retrieval, you need the actual node.
Correct Approach:
- For get(): Traverse to the target node (start from
dummy_head.next
, moveindex
times) - For insert/delete: Traverse to the predecessor (start from
dummy_head
, moveindex
times)
3. Forgetting to Update the Size Counter
Pitfall Example:
def addAtIndex(self, index: int, val: int) -> None:
if index > self.size:
return
predecessor = self.dummy_head
for _ in range(index):
predecessor = predecessor.next
new_node = ListNode(val, predecessor.next)
predecessor.next = new_node
# Forgot: self.size += 1
Solution: Always remember to:
- Increment
size
after successful insertion - Decrement
size
after successful deletion - Never modify
size
when operations fail due to invalid indices
4. Incorrect Boundary Validation
Pitfall Example:
# Incorrect boundary check for addAtIndex
def addAtIndex(self, index: int, val: int) -> None:
if index >= self.size: # Wrong! Should be index > self.size
return
Why it's wrong: When index == self.size
, we should append to the end of the list (valid operation). The condition should only reject when index > self.size
.
Correct Validation Rules:
- get(): Valid range is
[0, size-1]
- addAtIndex(): Valid range is
[0, size]
(can insert at the end) - deleteAtIndex(): Valid range is
[0, size-1]
5. Memory Leak in Deletion
Pitfall Example:
def deleteAtIndex(self, index: int) -> None:
predecessor = self.dummy_head
for _ in range(index):
predecessor = predecessor.next
predecessor.next = predecessor.next.next # Skips the node
# Missing: Setting deleted node's next to None
Why it matters: While Python's garbage collector will eventually clean up the node, explicitly setting node_to_delete.next = None
is good practice as it:
- Helps garbage collection happen sooner
- Prevents potential circular reference issues
- Makes the code's intent clearer
Best Practice:
node_to_delete = predecessor.next
predecessor.next = node_to_delete.next
node_to_delete.next = None # Explicitly break the reference
Which of the following shows the order of node visit in a Breadth-first Search?
Recommended Readings
Linked List Cycle Given a linked list with potentially a loop determine whether the linked list from the first node contains a cycle in it For bonus points do this with constant space Parameters nodes The first node of a linked list with potentially a loop Result Whether there is a loop contained
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Want a Structured Path to Master System Design Too? Don’t Miss This!