This article contains insertion of the node of doubly-linked list at various position:
- Insert node before head in DLL.
- Insert node before tail in DLL.
- Insert node before (kth node) in DLL.
- Insert before given node in DLL.
1️⃣ Insert Node Before Head in DLL
Problem Statement
Given the head of a doubly linked list and an integer X, insert a node with value X before the head of the linked list and return the head of the modified list.
Examples
Example 1:
Input: head -> 1 <-> 2 <-> 3, X = 3
Output: head -> 3 <-> 1 <-> 2 <-> 3
Explanation: 3 was added before the 1st node. Note that the head's value is changed.
Example 2:
Input: head -> 5, X = 7
Output: head -> 7 <-> 5
Intuition:
Insert a new node at the beginning of a doubly linked list, create a new node, link it to the current head, make the new node the head, and adjust the previous pointer of the original head.
Approach:
- Create a new node with the given value and set its back pointer to null and front pointer to the current head.
- Update the current head's back pointer to point to the new node.
- Return the new node as the updated head of the doubly linked list.
Code:
#include <bits/stdc++.h>
using namespace std;
// Definition of doubly linked list
struct ListNode
{
int val;
ListNode *next;
ListNode *prev;
ListNode()
{
val = 0;
next = NULL;
prev = NULL;
}
ListNode(int data1)
{
val = data1;
next = NULL;
prev = NULL;
}
ListNode(int data1, ListNode *next1, ListNode *prev1)
{
val = data1;
next = next1;
prev = prev1;
}
};
// Solution class
class Solution {
public:
/* Function to insert a node before
head in a doubly linked list */
ListNode* insertBeforeHead(ListNode* head, int X) {
// Create new node which will be the new head
ListNode* newHead = new ListNode(X, head, nullptr);
// Point the current head back to new one
head->prev = newHead;
return newHead; // Return new head
}
};
// Helper Function to convert an array to a doubly linked list
ListNode* arrayToLinkedList(vector<int> &nums) {
// If array is empty, return nullptr
if (nums.empty()) return nullptr;
// Create head node with first element of the array
ListNode* head = new ListNode(nums[0]);
// Initialize 'prev' to the head node
ListNode* prev = head;
for (int i=1; i < nums.size(); i++) {
// Create a new node
ListNode* temp = new ListNode(nums[i], nullptr, prev);
// Update 'next' pointer
prev->next = temp;
// Move 'prev' to newly created node
prev = temp;
}
// Return head
return head;
}
// Helper Function to print the linked list
void printLL(ListNode* head) {
while (head != NULL) {
cout << head->val << " ";
head = head->next;
}
cout << endl;
}
int main() {
vector<int> nums = {2, 3, 4, 5};
// Creating the doubly linked list from given array
ListNode* head = arrayToLinkedList(nums);
// Print the Original list
cout << "Original List: ";
printLL(head);
// Create an instance of Solution class
Solution sol;
/* Function call to insert a node before
head in a doubly linked list */
head = sol.insertBeforeHead(head, 1);
// Print the Modified list
cout << "Modified list: ";
printLL(head);
return 0;
}
Complexity Analysis:
- Time Complexity:
O(1)
because only a constant number of pointer updates are being performed regardless of the size of the Doubly Linked List. - Space Complexity:
O(1)
as no extra space is used.
2️⃣ Insert Node Before Tail in DLL
Problem Statement
Given the head of a doubly linked list and an integer X, insert a node with value X before the tail of the linked list and return the head of the modified list.
Examples
Example 1:
Input: head -> 1 <-> 2 <-> 4, X = 3
Output: head -> 1 <-> 2 <-> 3 <-> 4
Explanation: 3 was added before the last node.
Example 2:
Input: head -> 4, X = 6
Output: head -> 6 <-> 4
Explanation: 6 was added before 4, note that the head was changed as a result.
Intuition:
Inserting a node before the tail of a doubly linked list involves traversing the list to locate the second-to-last node. Once found, a new node is created, and the pointers of the adjacent nodes are updated to place the new node correctly before the tail. This maintains the list structure and ensures the new node is properly integrated.
Approach:
- Traverse to the tail of the linked list, keeping track of both the tail and the node previous to the tail.
- Create a new node with the given value, setting its next pointer to the tail and its back pointer to the previous node.
- Update the next pointer of the previous node to point to the new node and the back pointer of the tail to point to the new node, effectively inserting the new node before the tail.
Code:
#include <bits/stdc++.h>
using namespace std;
// Definition of doubly linked list
struct ListNode
{
int val;
ListNode *next;
ListNode *prev;
ListNode()
{
val = 0;
next = NULL;
prev = NULL;
}
ListNode(int data1)
{
val = data1;
next = NULL;
prev = NULL;
}
ListNode(int data1, ListNode *next1, ListNode *prev1)
{
val = data1;
next = next1;
prev = prev1;
}
};
// Solution class
class Solution {
public:
// Function to insert a node before tail of a doubly linked list
ListNode* insertBeforeTail(ListNode* head, int X) {
// Edge case
if (head->next == nullptr) {
// Create new node with data as X
ListNode* newHead = new ListNode(X, head, nullptr);
head->prev = newHead;
return newHead;
}
// Create pointer tail
ListNode* tail = head;
while (tail->next != nullptr) {
tail = tail->next;
}
// Keep track of node before tail using prev
ListNode* prev = tail->prev;
// Create new node with value X
ListNode* newNode = new ListNode(X, tail, prev);
// Join the new node
prev->next = newNode;
tail->prev = newNode;
// Return updated linked list
return head;
}
};
// Helper Function to convert an array to a doubly linked list
ListNode* arrayToLinkedList(vector<int> &nums) {
// If array is empty, return nullptr
if (nums.empty()) return nullptr;
// Create head node with first element of the array
ListNode* head = new ListNode(nums[0]);
// Initialize 'prev' to the head node
ListNode* prev = head;
for (int i=1; i < nums.size(); i++) {
// Create a new node
ListNode* temp = new ListNode(nums[i], nullptr, prev);
// Update 'next' pointer
prev->next = temp;
// Move 'prev' to newly created node
prev = temp;
}
// Return head
return head;
}
// Helper Function to print the linked list
void printLL(ListNode* head) {
while (head != NULL) {
cout << head->val << " ";
head = head->next;
}
cout << endl;
}
int main() {
vector<int> nums = {1, 2, 3, 5};
// Creating the doubly linked list from given array
ListNode* head = arrayToLinkedList(nums);
// Print the Original list
cout << "Original List: ";
printLL(head);
// Create an instance of Solution class
Solution sol;
/* Function call to insert a node
before tail of a doubly linked list */
head = sol.insertBeforeTail(head, 4);
// Print the Modified list
cout << "Modified list: ";
printLL(head);
return 0;
}
Complexity Analysis:
- Time Complexity:
O(N)
where N is the length of the array. We iterate through the input array exactly once and at each element perform constant time operations. - Space Complexity:
O(1)
as no extra space is used.
3️⃣ Insert Node Before (kth node) in DLL
Problem Statement:
Given the head of a doubly linked list and two integers X and K, insert a new node with value X, before the Kth node of the linked list and return the head of the modified linked list.
Examples:
Example 1:
Input: head -> 1 <-> 3 <-> 5, X = 7, K = 2
Output: head -> 1 <-> 7 <-> 3 <-> 5
Explanation: A node with value 7 was added before the 2nd node.
Example 2:
Input: head -> 1 <-> 3 <-> 5, X = 7, K = 2
Output: head -> 1 <-> 7 <-> 3 <-> 5
Explanation: A node with value 7 was added before the 2nd node.
Intuition:
Inserting a node in front of the Kth node in a doubly linked list involves first locating the Kth node by counting up to the Kth position. Then, adjust the pointers of the adjacent nodes to insert the new node before the Kth node.
Approach:
- Traverse the doubly linked list until reaching the Kth node, keeping a count. When the count reaches K, stop the traversal. Use a temporary pointer to mark the Kth node.
- Identify the node before the Kth node and prepare a new node with the required data, setting its previous and next pointers to the appropriate nodes.
- Update the next pointer of the node before the Kth node to point to the new node, and update the back pointer of the Kth node to point to the new node.
Code:
#include <bits/stdc++.h>
using namespace std;
// Definition of doubly linked list
struct ListNode
{
int val;
ListNode *next;
ListNode *prev;
ListNode()
{
val = 0;
next = NULL;
prev = NULL;
}
ListNode(int data1)
{
val = data1;
next = NULL;
prev = NULL;
}
ListNode(int data1, ListNode *next1, ListNode *prev1)
{
val = data1;
next = next1;
prev = prev1;
}
};
// Solution class
class Solution {
public:
/* Function to insert a node before the
Kth node in a doubly linked list */
ListNode* insertBeforeKthPosition(ListNode* head, int X, int K) {
// If node has to be inserted before the head
if (K == 1) {
ListNode* newHead = new ListNode(X, head, nullptr);
head->prev = newHead;
return newHead;
}
// Temporary pointer
ListNode* temp = head;
// Reach kth node
int count = 0;
while (temp != nullptr) {
count++;
// If kth node is reached, Break out of the loop
if (count == K) break;
// Otherwise Keep moving temp forward
temp = temp->next;
}
// Track the node
ListNode* prev = temp->prev;
// Create new node with data as X
ListNode* newNode = new ListNode(X, temp, prev);
// Join new node
prev->next = newNode;
temp->prev = newNode;
// Return head
return head;
}
};
// Helper Function to convert an array to a doubly linked list
ListNode* arrayToLinkedList(vector<int> &nums) {
// If array is empty, return nullptr
if (nums.empty()) return nullptr;
// Create head node with first element of the array
ListNode* head = new ListNode(nums[0]);
// Initialize 'prev' to the head node
ListNode* prev = head;
for (int i=1; i < nums.size(); i++) {
// Create a new node
ListNode* temp = new ListNode(nums[i], nullptr, prev);
// Update 'next' pointer
prev->next = temp;
// Move 'prev' to newly created node
prev = temp;
}
// Return head
return head;
}
// Helper Function to print the linked list
void printLL(ListNode* head) {
while (head != NULL) {
cout << head->val << " ";
head = head->next;
}
cout << endl;
}
int main() {
vector<int> nums = {1, 2, 3, 5};
// Creating the doubly linked list from given array
ListNode* head = arrayToLinkedList(nums);
// Print the Original list
cout << "Original List: ";
printLL(head);
// Create an instance of Solution class
Solution sol;
/* Function call to insert a node before the
Kth node in a doubly linked list */
head = sol.insertBeforeKthPosition(head, 4, 4);
// Print the Modified list
cout << "Modified list: ";
printLL(head);
return 0;
}
Complexity Analysis:
- Time Complexity:
O(N)
, where N is the number of nodes in the Linked List. In the worst case, it involves traversing N nodes in the Doubly Linked List to reach the last element. In the best case, when K is 0 (insertion at the head), the time complexity is O(1) as it involves a constant number of operations. In the average case, it's O(K). - Space Complexity:
O(1)
as no extra space is used.
4️⃣ Insert Before Given Node in DLL
Given a node's reference within a doubly linked list and an integer X, insert a node with value X before the given node in the linked list while preserving the list's integrity.
You will only be given the node's reference, not the head of the list. It is guaranteed that the given node will not be the head of the list.
Examples:
Example 1:
Input: head -> 1 <-> 2 <-> 6, node = 2, X = 7
Output: head -> 1 <-> 7 <-> 2 <-> 6
Explanation: Note that the head was not given to the function.
Example 2:
Input: head -> 7 <-> 5 <-> 5, node = 5 (node 3), X = 10
Output: head -> 7 <-> 5 <-> 10 <-> 5
Explanation: The last node with value 5 was referenced, thus the new node was added before the last node.
Intuition:
Identify the preceding node, create a new node and insert it between the identified node and its successor, then readjust links.
Approach:
- Track the node to which the back pointer of the referenced node is pointing, and call it the previous node.
- Create a new node with its data as the given value, its back pointer as the previous node, and its next pointer as the referenced node.
- Update the next pointer of the previous node to point to the newly created node.
Code:
#include <bits/stdc++.h>
using namespace std;
// Definition of doubly linked list
struct ListNode
{
int val;
ListNode *next;
ListNode *prev;
ListNode()
{
val = 0;
next = NULL;
prev = NULL;
}
ListNode(int data1)
{
val = data1;
next = NULL;
prev = NULL;
}
ListNode(int data1, ListNode *next1, ListNode *prev1)
{
val = data1;
next = next1;
prev = prev1;
}
};
// Solution class
class Solution {
public:
/* Function to insert a new node before
given node in a doubly linked list */
void insertBeforeGivenNode(ListNode* node, int X) {
// Get node before the given node
ListNode* prev = node->prev;
// Create new node
ListNode* newNode = new ListNode(X, node, prev);
// Connect newNode
prev->next = newNode;
node->prev = newNode;
// void function to just update
return;
}
};
// Helper Function to convert an array to a doubly linked list
ListNode* arrayToLinkedList(vector<int> &nums) {
// If array is empty, return nullptr
if (nums.empty()) return nullptr;
// Create head node with first element of the array
ListNode* head = new ListNode(nums[0]);
// Initialize 'prev' to the head node
ListNode* prev = head;
for (int i=1; i < nums.size(); i++) {
// Create a new node
ListNode* temp = new ListNode(nums[i], nullptr, prev);
// Update 'next' pointer
prev->next = temp;
// Move 'prev' to newly created node
prev = temp;
}
// Return head
return head;
}
// Helper Function to print the linked list
void printLL(ListNode* head) {
while (head != NULL) {
cout << head->val << " ";
head = head->next;
}
cout << endl;
}
int main() {
vector<int> nums = {1, 2, 4, 5};
// Creating the doubly linked list from given array
ListNode* head = arrayToLinkedList(nums);
// Node before which the new node must be inserted
ListNode* node = head-> next-> next;
// Print the Original list
cout << "Original List: ";
printLL(head);
// Create an instance of Solution class
Solution sol;
/* Function call to insert a new node before
given node in a doubly linked list */
sol.insertBeforeGivenNode(node, 3);
// Print the Modified list
cout << "Modified list: ";
printLL(head);
return 0;
}
Complexity Analysis:
- Time Complexity:
O(1)
because only a constant number of pointer updates are being performed regardless of the size of the Doubly Linked List. - Space Complexity:
O(1)
as no extra space is used.