Top linked list interview questions and answers
A linked list is a linear data structure consisting of connected nodes placed in a non-contiguous manner in the memory. Each node typically consists of an associated value and a pointer to the next node.
Linked lists are crucial in solving quite a lot of problems, and they constitute a major part of interviews containing data structures. The following blog covers diverse questions on linked lists, including the problem statement, the intuition behind solving the problem, the code and a detailed explanation following the code. We also discuss the time and space complexity for each solution to assess the efficiency. The diversity of questions will equip you to be prepared for many similar questions, and by the end of this blog, you will learn algorithms like the Hare and Tortoise algorithm to solve linked list problems efficiently.
1. How to reverse a linked list#
Problem statement#
The problem at hand is to reverse a linked list in-place, i.e., to change the direction of the links between nodes so that the last node becomes the first node, the second-to-last node becomes the second node, and so on.
Intuition#
A linked list can be reversed by applying various methods, such as using a data structure (e.g., a stack), using recursion, or through an iterative process. We’ll be using an iterative approach to reverse a linked list because such an approach doesn’t require extra auxiliary space. The intuition behind the iterative approach will be to change the next pointers of each node to start pointing to the previous node instead.
Code#
Let’s code this solution and go through its implementation in detail.
Code explanation#
A node
curris defined to keep track of the current node. It’s initially set toheadPtrbecause the iteration starts from the head pointer.A node
previs defined to keep track of the current node’s previous node. It is initially set tonullbecause there’s no previous node for the head pointer (headPtr).A node
nextis defined to keep track of the node directly after the current node. It’s initially set tonulland will be updated within the loop.A
whileloop first ensures whether the current node exists. In case it does, the following assignments are made:The
nextnode is updated to store the pointer after the current node by accessing it throughcurrent.nextPtr.To reverse the linked list, the pointer pointing toward the next node of the current node is made to point to the previous node of the current node. This simply reverses the direction of the links between the nodes one by one.
The
prevnode is now made to point to the current node for the next iteration.The
currnode is updated to point to the next node of the current node, stored innext, for the next iteration.
Once the list is completely traversed, the head node
headPtris updated to the updated current value, i.e., the last node after the complete traversal. The list is now completely reversed, andheadPtris pointing to the last node.
Time and space complexity#
The linked list is traversed only once while changing the direction of the next pointers of each node, resulting in a time complexity of
2. Finding the middle of a linked list#
Problem statement#
The problem at hand is to find the middle node of a linked list. If the length of the linked list is odd, there is only one middle node. Otherwise, there are two middle nodes, and either of them can be returned.
Intuition#
One approach could be to make two traversals, one for counting the length
Code#
Let’s code this solution and go through its implementation in detail.
Code explanation#
The
findMiddle()method returns null if no middle pointer is found, i.e., the list is empty.If there’s only one element, i.e., the
headPtrnode, it’s returned as the middle element.If there are two elements in the list, the
headPtrand theheadPtr.nextPtrnodes, any node can be returned as the middle element. Here, we return theheadPtrnode.For multiple elements, two pointers,
slowPtrandfastPtr, are initialized to theheadPtrnode. TheslowPtrpointer traverses each node one by one, while thefastPtrpointer skips one node each time.By the time the
fastPtrpointer reaches the end of the linked list, theslowPtrpointer has reached the middle of the list, therefore obtaining the middle value.
This node is then returned by the findMiddle() method.
Time and space complexity#
Because we’re traversing the entire list linearly, the time complexity is
3. Removing duplicates in a sorted linked list#
Problem statement#
The task at hand is to remove duplicates from a sorted linked list. Removing duplicates means that we have to eliminate nodes with duplicate values. This leaves only distinct values in the linked list.
Intuition#
We know that the linked list is sorted, so the duplicates will occur consecutively. To remove duplicates, we can simply iterate through the list, comparing each node’s value with the next one. If two consecutive nodes are equal, we then update the next pointer of the current node to skip the duplicate node.
Code#
Let’s delve into the implementation of this solution.
Code explanation#
A pointer named
currentis used to traverse the linked list.The
whileloop ensures that the end of the list is not reached.Within the loop, it’s checked if a duplicate is found or not. If the
currentnode’s value is equal to the value of its next node, the next pointer of thecurrentnode is updated to skip the duplicate node.If no duplicate is found, the
currentpointer is moved to the next node to check with the further nodes.The process continues until the end of the list is reached.
Time and space complexity#
Because we’re traversing the entire list only once, the time complexity is
4. Detecting a loop in a linked list#
Problem statement#
The challenge is to identify the presence of a loop in a linked list. A loop occurs when a node in the list points to a node present earlier in the list, forming a cycle within the linked structure.
Intuition#
To detect a loop, we can use Floyd’s Tortoise and Hare algorithm, a very crucial algorithm when it comes to linked lists. It involves two pointers moving through the list at different speeds. If there’s a loop, the two pointers will meet one way or another. The slow pointer advances one node at a time, and at the same time, the fast pointer advances two nodes at a time.
Code#
Let’s delve into the implementation of this solution.
Code explanation#
Two pointers,
tortoiseandhare, are both initialized to the head of the linked list.The
whileloop continues until theharenode reaches the end of the list or a loop is detected.The
whileloop ensures that theharepointer points to a valid node and, if it does, also ensures that the next node for theharepointer exists. These two checks remove the chances of accessing an empty node in case the linked list was completely traversed in the previous iteration (therefore removing any chances of error).In each iteration, the tortoise node moves one step, and the
harenode moves two steps. We do this by assigning the next pointer of the tortoise node to thetortoisenode and the next-to-next pointer of the hare node to theharenode.If there’s a loop, the two pointers will meet at some point within the loop.
If no loop is present, the
harenode will reach the end of the list, and the loop detection process will simply end.
Time and space complexity#
The time complexity for the above code is
5. Converting a singly linked list into a circular linked list#
Problem statement#
The objective here is to convert a singly linked list into a circular linked list. Let’s understand a circular linked list first. In a circular linked list, the last node’s next pointer is not null but points back to the head of the list, forming a loop.
Intuition#
To convert a singly linked list into a circular one, we can simply set the next pointer of the last node to point back to the head of the list.
Code#
Let’s delve into the implementation of this solution.
Code explanation#
The
convertToCircular()method first makes the necessary checks, i.e., if the linked list is empty. If it is, the function simply returns.The method is used to reach the last node within the linked list. This is achieved by moving through the list until the next pointer is
null.Once the last node is found, the next pointer of this node is updated to point back to the head of the list. This effectively makes a circular structure.
The
print()method is modified to accommodate circular linked lists. It uses ado-whileloop to print the values of the nodes until it returns to the head, ensuring all nodes in the circular list are displayed and the process doesn’t go on infinitely.
Time and space complexity#
The time complexity is
6. Inserting values in a sorted way in a doubly linked list DLL#
Problem statement#
The task at hand is to insert a value in sorted order within a doubly linked list. The doubly linked list is sorted in ascending order, and the important part is to maintain this ordering after the insertion.
Intuition#
To insert a value in sorted order, we can traverse the doubly linked list until we find the correct position for the new value. Once the position is identified, we create a new node and update its next and previous pointers to integrate it into the list.
Code#
Let’s delve into the implementation of this solution.
Code explanation#
The
insertSorted()method, first and foremost, creates a new node with the given value.If the list is empty, the new node becomes both the
headand thetail.If the value is less than the
headpointer’s data, i.e., the new node should be the first value, and the new node is inserted at the beginning.If the value is greater than the
tailpointer’s data, i.e., the new node should be the last, and the new node is inserted at the end.If none of the above conditions fit, the method begins to traverse the list to find the correct position for the new value. Once it’s found, the next and previous pointers of the neighboring nodes are updated to integrate the new node into the sorted list. The following points break down the details:
newNode.prev: Sets theprevpointer of the new node to theprevpointer of the current nodenewNode.next: Sets thenextpointer of the new node to thecurrentnodecurrent.prev.next: Updates the next pointer of the node before thecurrentnode to point to the new nodecurrent.prev: Updates theprevpointer of thecurrentnode to point to the new node
Time and space complexity#
The time complexity is
7. Finding the intersection point of two linked lists#
Problem statement#
The challenge here is to determine the intersection point of two linked lists. Let’s first understand what an intersection point is before moving on. An intersection point is simply a node at which both linked lists converge, arriving at the same (common) node.
Intuition#
To find the intersection point, we can first calculate the lengths of both linked lists. Then, we align the starting points of the lists by changing the starting position of the longer list. Once the distance from both of the starting points of the lists to the common node is the same, we iterate through both lists and compare nodes until we find the intersection point.
Code#
Let’s delve into the implementation of this solution.
Code explanation
The
findLength()method is responsible for calculating the length of a linked list. It traverses the list and uses a counterlengthto increase it for each node traversed.The
getIntersectionNode()method first finds the lengths of both linked lists using thefindLength()method.It then adjusts the starting positions of the lists so that they both have the same number of nodes left till the intersection point. This ensures that when we iterate through both lists, we reach the intersection point at the same time.
The iteration through the adjusted lists continues until either an intersection point is found (common node) or the end of one of the lists is reached.
If an intersection point is found, the common node is returned. Otherwise,
nullis returned.
Time and space complexity#
The time complexity is
8. Modify the values of the first half nodes in a singly linked list without using extra space#
Problem statement#
Given a singly linked list containing
Intuition#
To solve this problem while using
Code explanation#
Two pointers,
slowPtrandfastPtr, are used to traverse the linked list. ThefastPtrpointer moves twice as fast as theslowPtrpointer (it makes two jumps each time). WhenfastPtrreaches the end of the list,slowPtrreaches the middle.During this traversal, a
prevpointer keeps track of the node before theslowPtrnode.The second half of the list (starting from
slowPtr) is reversed using thereverse()function.The reversed second half is stored in the
secondHalfnode.The pointers
firstHalfandsecondHalftraverse the first half and the reversed second half simultaneously.Values of the first half nodes are modified by subtracting the current values from the corresponding values in the reversed second half.
The reversed second half is reversed again through the
reverse()function to restore it to the original order.The reversed second half is connected back to the original list.
Time and space complexity
Traversing the list to find the middle and reverse the second half takes
9. Merge kkk sorted linked lists#
Problem statement
Given an array of
Intuition#
To efficiently merge
Code explanation#
A method named
mergeKLists()created to perform the merge. If the list is empty, the method simply returns.A priority queue named
minHeapis created, and the elements added to it areListNodeobjects. The comparator used for ordering is implemented by the lambda expression(a, b) -> a.val - b.val, which ensures that the priority queue is a min-heap.Each linked list from the lists is iterated, and in case it is not empty, its head node is added to the min heap.
The code initializes a
dummynode and acurrentnode to keep track of the merged list. It then repeatedly extracts the minimum node from the min heap using theminHeap.poll()method and appends it to the merged list by updating current node’s next pointer with theminNodepointer. If the extracted node has a next node, it is added back to the min heap through theminHeap.offer(minNode.next)method call.At last, the method returns the merged sorted linked list and excludes the
dummynode.
Time and space complexity#
The time complexity of this algorithm is
10. Add two numbers represented using linked lists#
Problem statement#
Given two non-empty linked lists representing two nonnegative integers, where each node contains a single digit, our task here is to add the two numbers and return the sum as a linked list.
The digits are stored in reverse order, and each of their nodes contains a single digit. We add the two numbers and return the sum as a linked list.
Intuition#
We can traverse both linked lists simultaneously, adding corresponding digits. We also need to add the carry (if any) for each sum we make. We can create a new node for each sum digit and keep track of the carry for the next iteration. It’s very important to handle cases where one linked list is longer than the other or where there is a final carry.
Code explanation#
A
dummynamed node is created to act as the dummy head of our final sum linked list.A pointer named
currentis initialized to point to thedummynode. This pointer is used to traverse and build the new linked list.A variable
carryis initialized to0. It will store the carry generated during the addition of digits (if any).A
whileloop is used to iterate through the linked listsl1andl2.Inside the loop, the values of the current nodes in
l1andl2are extracted or set to0if any value isnull.The sum of the digits, along with the carry from the previous step, is calculated.
The carry for the next iteration is updated based on the sum divided by 10.
A new node is created in the
resultlist, with the value being the remainder of the sum when divided by 10. This step ensures that only the last digit is added to theresultlist.The
currentpointer is moved to thenextnode in theresultlist.The pointers
l1andl2are moved to their respective next nodes.After the loop, a check is made to see if there’s any remaining carry. If there is, a new node is added to the
resultlist with the carry.The function returns the next node of the
dummyhead, which represents the actual head of the result list.
Note: The answer obtained has its digits reversed.
Time and space complexity#
The time complexity for this question is