Facebook Pixel

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:

  1. MyLinkedList(): Constructor that initializes an empty linked list.

  2. get(index): Returns the value of the node at the given index position (0-indexed). If the index is invalid (negative or greater than or equal to the list size), return -1.

  3. addAtHead(val): Inserts a new node with value val at the beginning of the linked list. This new node becomes the first node.

  4. addAtTail(val): Appends a new node with value val at the end of the linked list.

  5. addAtIndex(index, val): Inserts a new node with value val at the specified index 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
  6. deleteAtIndex(index): Removes the node at the given index 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 with val and next 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)
Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

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:

  1. Start with a reference to either dummy (for insertion/deletion) or dummy.next (for getting values)
  2. Move forward index times to reach the desired position
  3. 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 contains val (the data) and next (pointer to the next node)
  • dummy: A sentinel node that remains before the first actual element
  • cnt: 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:

  1. First validates if index is within bounds [0, cnt-1]
  2. Starts traversal from dummy.next (the first actual node)
  3. Moves forward index times to reach the target node
  4. Returns the value at that position or -1 if invalid

addAtIndex(index, val) - Core Insertion Logic:

  1. Validates that index <= cnt (can insert at the end when index == cnt)
  2. Finds the predecessor node by starting from dummy and moving index steps
  3. 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
  4. Increments the counter

addAtHead(val) and addAtTail(val):

  • Simply delegate to addAtIndex:
    • Head insertion: addAtIndex(0, val)
    • Tail insertion: addAtIndex(cnt, val)

deleteAtIndex(index) Method:

  1. Validates that index < cnt (must be an existing node)
  2. Finds the predecessor by traversing from dummy for index steps
  3. Saves reference to the node to be deleted (t = pre.next)
  4. Bypasses the node by setting pre.next = t.next
  5. Cleans up by setting t.next = None (helps garbage collection)
  6. Decrements the counter

Time Complexity:

  • get: O(n) where n is the index
  • addAtHead: O(1)
  • addAtTail: O(n) where n is the list size
  • addAtIndex: O(n) where n is the index
  • deleteAtIndex: 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 Evaluator

Example 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 counter
  • get(index): O(n) - Traverses from the dummy node to the index position, where n is the index value
  • addAtHead(val): O(1) - Calls addAtIndex(0, val) which only needs to traverse 0 nodes
  • addAtTail(val): O(n) - Calls addAtIndex(self.cnt, val) which traverses n nodes where n is the length of the list
  • addAtIndex(index, val): O(index) or O(n) - Traverses from dummy node to the index position, worst case is O(n) when inserting at tail
  • deleteAtIndex(index): O(index) or O(n) - Traverses from dummy node to the index position, worst case is O(n) when deleting the last element

Space Complexity:

  • __init__(): O(1) - Only creates one dummy node
  • get(index): O(1) - Uses only a single pointer variable for traversal
  • addAtHead(val): O(1) - Creates one new node
  • addAtTail(val): O(1) - Creates one new node
  • addAtIndex(index, val): O(1) - Creates one new node and uses a pointer for traversal
  • deleteAtIndex(index): O(1) - Uses two pointer variables for traversal and deletion
  • Overall space complexity for the data structure: O(n) where n 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, move index times)
  • For insert/delete: Traverse to the predecessor (start from dummy_head, move index 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
Discover Your Strengths and Weaknesses: Take Our 3-Minute Quiz to Tailor Your Study Plan:

Which of the following shows the order of node visit in a Breadth-first Search?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More