0% found this document useful (0 votes)
214 views64 pages

1.write A Program To Reverse The Linked List. (Both Iterative and Recursive)

The document discusses various approaches to solve common problems with linked lists, including reversing a linked list iteratively and recursively, reversing a linked list in groups of a given size, detecting loops in a linked list, and marking visited nodes in a linked list without modifying its data structure. Iterative and recursive algorithms with code examples are provided for reversing single linked lists. Approaches like using stacks, arrays, and two pointers are described for detecting loops and reversing in groups.

Uploaded by

Vinay Vyas
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
214 views64 pages

1.write A Program To Reverse The Linked List. (Both Iterative and Recursive)

The document discusses various approaches to solve common problems with linked lists, including reversing a linked list iteratively and recursively, reversing a linked list in groups of a given size, detecting loops in a linked list, and marking visited nodes in a linked list without modifying its data structure. Iterative and recursive algorithms with code examples are provided for reversing single linked lists. Approaches like using stacks, arrays, and two pointers are described for detecting loops and reversing in groups.

Uploaded by

Vinay Vyas
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 64

LINKED LIST

1.Write a Program to reverse the Linked List. (Both Iterative and recursive)
ITERATIVE:
LOGIC:
Initialize three pointers prev as NULL, curr as head and next as NULL.
Iterate through the linked list. In a loop, do the following.

// Before changing next of current,


// store next node

next = curr->next

// Now change next of current


// This is where actual reversing happens

curr->next = prev

// Move prev and curr one step forward

prev = curr
curr = next

CODE:
void reverse()
{ // Initialize current, previous and
// next pointers
Node* current = head;
Node *prev = NULL, *next = NULL;

while (current != NULL) {


// Store next
next = current->next;

// Reverse current node's pointer


current->next = prev;

// Move pointers one position ahead.


prev = current;
current = next;
}
head = prev;
}
Time Complexity: O(n)
Space Complexity: O(1)

RECURSIVE :
Divide the list in two parts - first node and
rest of the linked list.
2) Call reverse for the rest of the linked list.
3) Link rest to first.
4) Fix head pointer

CODE:
Node* reverse(Node* head)
{
if (head == NULL || head->next == NULL)
return head;

/* reverse the rest list and put


the first element at the end */
Node* rest = reverse(head->next);
head->next->next = head;

/* tricky step -- see the diagram */


head->next = NULL;

/* fix the head pointer */


return rest;
}
Time Complexity: O(n)
Space Complexity: O(1)

SOME DIFFERENT APPROACHES

1.USING STACKS
Store the nodes(values and address) in the stack until all the values are entered.
Once all entries are done, Update the Head pointer to the last location(i.e the last value).
Start popping the nodes(value and address) and store them in the same order until the stack
is empty.
Update the next pointer of last Node in the stack by NULL.

void reverseLL(Node** head)


{ // Create a stack "s"
// of Node type
stack<Node*> s;
Node* temp = *head;
while (temp->next != NULL)
{
// Push all the nodes
// in to stack
s.push(temp);
temp = temp->next;
}
*head = temp;

while (!s.empty())
{ // Store the top value of
// stack in list
temp->next = s.top();

// Pop the value from stack


s.pop();

// update the next pointer in the


// in the list
temp = temp->next;
}
temp->next = NULL;
}

2.Using array
1.Create a linked list
2. Then, make a count(head) function to count the number of nodes.

3. Initialize an array with the size of the count.

4. and start a while(p->next!=NULL) loop and store all the node’s data into the array.

5. and then print the array from the last index to the first.

node *ll_reverse(node* head) // to reverse the linked list


{
node* p=head;
long int i=count(head),
Int j=1;
long int arr[i];

while(i && p!=NULL)


{
arr[j++]=p->val;
p=p->next;
i--;
}
j--;

while(j) // loop will break as soon as j=0


{
cout<<arr[j--]<<" ";
}

return head;
}

2.Reverse a Linked List in a group of Given Size. [Very Imp]

LOGIC:

Algorithm: reverse(head, k)
Reverse the first sub-list of size k. While reversing, keep track of the next node and previous
node. Let the pointer to the next node be next and pointer to the previous node be prev.
head->next = reverse(next, k) ( Recursively call for rest of the list and link the two sub-lists)

Return prev ( prev becomes the new head of the list) .


CODE :
* Reverses the linked list in groups
of size k and returns the pointer
to the new head node. */
Node* reverse(Node* head, int k)
{
// base case
if (!head)
return NULL;
Node* current = head;
Node* next = NULL;
Node* prev = NULL;
int count = 0;

/*reverse first k nodes of the linked list */


while (current != NULL && count < k) {
next = current->next;
current->next = prev;
prev = current;
current = next;
count++;
}
/* next is now a pointer to (k+1)th node
Recursively call for the list starting from current.
And make rest of the list as next of first node */
if (next != NULL)
head->next = reverse(next, k);

/* prev is new head of the input list */


return prev;
}
Time Complexity: O(n).
Traversal of list is done only once and it has ‘n’ elements.

Auxiliary Space: O(n/k).


For each Linked List of size n, n/k or (n/k)+1 calls will be made during the recursion.

APPROACH 2

We have used a stack which will store the nodes of the given linked list. Firstly, push the k
elements of the linked list in the stack. Now pop elements one by one and keep track of the
previously popped node. Point the next pointer of prev node to top element of stack. Repeat
this process, until NULL is reached.

This algorithm uses O(k) extra space.

/* Reverses the linked list in groups of size k


and returns the pointer to the new head node. */

struct Node* Reverse(struct Node* head, int k)


{
// Create a stack of Node*
stack<Node*> mystack;
struct Node* current = head;
struct Node* prev = NULL;

while (current != NULL) {

// Terminate the loop whichever comes first


// either current == NULL or count >= k
int count = 0;
while (current != NULL && count < k) {
mystack.push(current);
current = current->next;
count++;
}

// Now pop the elements of stack one by one


while (mystack.size() > 0) {

// If the final list has not been started yet.


if (prev == NULL) {
prev = mystack.top();
head = prev;
mystack.pop();
} else {
prev->next = mystack.top();
prev = prev->next;
mystack.pop();
}
}
}

// Next of last element will point to NULL.


prev->next = NULL;
return head;
}

3.Write a program to Detect loop in a linked list.

APPROACH : Traverse the list one by one and keep putting the node addresses in a Hash Table. At any
point, if NULL is reached then return false, and if the next of the current nodes points to any of the
previously stored nodes in Hash then return true.

// Returns true if there is a loop in linked list


// else returns false.
bool detectLoop(struct Node* h)
{
unordered_set<Node*> s;

while (h != NULL) {
// If this node is already present
// in hashmap it means there is a cycle
// (Because you we encountering the
// node for the second time).
if (s.find(h) != s.end())
return true;

// If we are seeing the node for


// the first time, insert it in hash
s.insert(h);

h = h->next;
}

return false;
}
Time complexity: O(n).
Only one traversal of the loop is needed.
Auxiliary Space: O(n).
n is the space required to store the value in hashmap.

ALGORITHM

This solution requires modifications to the basic linked list data structure.
Have a visited flag with each node.
Traverse the linked list and keep marking visited nodes.
If you see a visited node again then there is a loop. This solution works in O(n) but requires
additional information with each node.
A variation of this solution that doesn’t require modification to basic data structure can be
implemented using a hash, just store the addresses of visited nodes in a hash and if you see
an address that already exists in hash then there is a loop.
CODE :

Returns true if there is a loop in linked list


// else returns false.

bool detectLoop(struct Node* h)


{
while (h != NULL) {
// If this node is already traverse
// it means there is a cycle
// (Because you we encountering the
// node for the second time).
if (h->flag == 1)
return true;

// If we are seeing the node for


// the first time, mark its flag as 1
h->flag = 1;

h = h->next;
}
return false;
}
Time complexity:O(n).
Only one traversal of the loop is needed.
Auxiliary Space:O(1).
No extra space is needed.

APPROACH:
Traverse linked list using two pointers.

Move one pointer(slow_p) by one and another pointer(fast_p) by two.

If these pointers meet at the same node then there is a loop. If pointers do not meet
then linked list doesn’t have a loop
int detectLoop(Node* list)

{ Node *slow_p = list, *fast_p = list;


while (slow_p && fast_p && fast_p->next)
{
slow_p = slow_p->next;
fast_p = fast_p->next->next;
if (slow_p == fast_p) {
return 1;
}
}
return 0;
}
Time complexity: O(n).
Only one traversal of the loop is needed.

Auxiliary Space:O(1).
There is no space required.

APPROACH: marking visited nodes without modifying the linked list data structure

In this method, a temporary node is created. The next pointer of each node that is traversed
is made to point to this temporary node. This way we are using the next pointer of a node as
a flag to indicate whether the node has been traversed or not. Every node is checked to see
if the next is pointing to a temporary node or not. In the case of the first node of the loop, the
second time we traverse it this condition will be true, hence we find that loop exists. If we
come across a node that points to null then the loop doesn’t exist.

// Function to detect first node of loop


// in a linked list that may contain loop
bool detectLoop(Node* head)
{

// Create a temporary node


Node* temp = new Node;
while (head != NULL) {

// This condition is for the case


// when there is no loop
if (head->next == NULL) {
return false;
}

// Check if next is already


// pointing to temp
if (head->next == temp) {
return true;
}

// Store the pointer to the next node


// in order to get to it in the next step
Node* nex = head->next;

// Make next point to temp


head->next = temp;
// Get to the next node in the list
head = nex;
}

return false;
}

● Time complexity: O(n).


Only one traversal of the loop is needed.
● Auxiliary Space: O(1).
There is no space required

APPROACH :

This is the simplest approach to the given problem, the only thing we have to do is to assign
a new value to each node in the linked list which is not in the range given.
Example suppose (1 <= Data on Node <= 10^3) then after visiting node assign the
data as -1 as it is out of the given range.

CODE :
// Function to detect first node of loop
// in a linked list that may contain loop

bool detectLoop(Node* head)


{

// If the head is null we will return false


if (!head)
return 0;
else {

// Traversing the linked list


// for detecting loop
while (head) {
// If loop found
if (head->key == -1) {
return true;
}

// Changing the data of visited node to any


// value which is outside th given range here it
// is supposed the given range is (1 <= Data on
// Node <= 10^3)
else {
head->key = -1;
head = head->next;
}
}
// If loop not found return false
return 0;
}
}
Time Complexity: O(N) ,Auxiliary Space: O(1)
4.Write a program to Delete loop in a linked list.

/* Function to remove loop.


Used by detectAndRemoveLoop() */

void removeLoop(struct Node*, struct Node*);

/* This function detects and


removes loop in the list
If loop was there in the
list then it returns 1,
otherwise returns 0 */
int detectAndRemoveLoop(struct Node* list)
{
struct Node *slow_p = list, *fast_p = list;

while (slow_p && fast_p && fast_p->next)


{
slow_p = slow_p->next;
fast_p = fast_p->next->next;

/* If slow_p and fast_p meet at


some point then
there is a loop */
if (slow_p == fast_p) {
removeLoop(slow_p, list);

/* Return 1 to indicate that loop is found */


return 1;
}
}

/* Return 0 to indeciate that ther is no loop*/


return 0;
}

/* Function to remove loop.


loop_node --> Pointer to
one of the loop nodes
head --> Pointer to the
start node of the linked list */
void removeLoop(struct Node* loop_node, struct Node* head)
{
struct Node* ptr1;
struct Node* ptr2;

/* Set a pointer to the beginning


of the Linked List and
move it one by one to find the
first node which is
part of the Linked List */
ptr1 = head;
while (1) {
/* Now start a pointer from
loop_node and check if
it ever reaches ptr2 */
ptr2 = loop_node;
while (ptr2->next != loop_node
&& ptr2->next != ptr1)
ptr2 = ptr2->next;

/* If ptr2 reahced ptr1


then there is a loop. So
break the loop */
if (ptr2->next == ptr1)
break;

/* If ptr2 did't reach ptr1


then try the next node
* after ptr1 */
ptr1 = ptr1->next;
}

/* After the end of loop ptr2


is the last node of the
loop. So make next of ptr2 as NULL */
ptr2->next = NULL;
}

Method 2 (Better Solution)

1. This method is also dependent on Floyd’s Cycle detection algorithm.


2. Detect Loop using Floyd’s Cycle detection algorithm and get the pointer to a loop
node.
3. Count the number of nodes in loop. Let the count be k.
4. Fix one pointer to the head and another to a kth node from the head.
5. Move both pointers at the same pace, they will meet at loop starting node.
6. Get a pointer to the last node of the loop and make next of it as NULL.

void removeLoop(struct Node* loop_node, struct Node* head)


{
struct Node* ptr1 = loop_node;
struct Node* ptr2 = loop_node;

// Count the number of nodes in loop


unsigned int k = 1, i;
while (ptr1->next != ptr2) {
ptr1 = ptr1->next;
k++;
}

// Fix one pointer to head


ptr1 = head;

// And the other pointer to k nodes after head


ptr2 = head;
for (i = 0; i < k; i++)
ptr2 = ptr2->next;

/* Move both pointers at the same pace,


they will meet at loop starting node */
while (ptr2 != ptr1) {
ptr1 = ptr1->next;
ptr2 = ptr2->next;
}

// Get pointer to the last node


while (ptr2->next != ptr1)
ptr2 = ptr2->next;

/* Set the next node of the loop ending node


to fix the loop */
ptr2->next = NULL;
}

Optimized and best :

We do not need to count number of nodes in Loop. After detecting the loop, if we start slow
pointer from head and move both slow and fast pointers at same speed until fast don’t meet,
they would meet at the beginning of the loop.

// Function to detect and remove loop


// in a linked list that may contain loop

void detectAndRemoveLoop(Node* head)


{
// If list is empty or has only one node
// without loop
if (head == NULL || head->next == NULL)
return;

Node *slow = head, *fast = head;

// Move slow and fast 1 and 2 steps


// ahead respectively.
slow = slow->next;
fast = fast->next->next;

// Search for loop using slow and


// fast pointers
while (fast && fast->next) {
if (slow == fast)
break;
slow = slow->next;
fast = fast->next->next;
}

/* If loop exists */
if (slow == fast)
{
slow = head;

// this check is needed when slow


// and fast both meet at the head of the LL
// eg: 1->2->3->4->5 and then
// 5->next = 1 i.e the head of the LL
if(slow == fast) {
while(fast->next != slow) fast = fast->next;
}
else {
while (slow->next != fast->next) {
slow = slow->next;
fast = fast->next;
}
}

/* since fast->next is the looping point */


fast->next = NULL; /* remove loop */
}
}
Hashing: Hash the address of the linked list nodes
We can hash the addresses of the linked list nodes in an unordered map and just check if
the element already exists in the map. If it exists, we have reached a node which already
exists by a cycle, hence we need to make the last node’s next pointer NULL.
// Function to detect and remove loop
// in a linked list that may contain loop
void hashAndRemove(Node* head)
{
// hash map to hash addresses of the linked list nodes
unordered_map<Node*, int> node_map;
// pointer to last node
Node* last = NULL;
while (head != NULL) {
// if node not present in the map, insert it in the map
if (node_map.find(head) == node_map.end())
{
node_map[head]++;
last = head;
head = head->next;
}
// if present, it is a cycle, make the last node's next pointer NULL
else {
last->next = NULL;
break;
}
}
}

5.Find the starting point of the loop.

If a loop is found, initialize a slow pointer to head, let fast pointer be at its position.
Move both slow and fast pointers one node at a time.
The point at which they meet is the start of the loop.
Function to detect and remove loop
// in a linked list that may contain loop
Node* detectAndRemoveLoop(Node* head)
{
// If list is empty or has only one node
// without loop
if (head == NULL || head->next == NULL)
return NULL;

Node *slow = head, *fast = head;

// Move slow and fast 1 and 2 steps


// ahead respectively.
slow = slow->next;
fast = fast->next->next;

// Search for loop using slow and


// fast pointers
while (fast && fast->next) {
if (slow == fast)
break;
slow = slow->next;
fast = fast->next->next;
}

// If loop does not exist


if (slow != fast)
return NULL;

// If loop exists. Start slow from


// head and fast from meeting point.
slow = head;
while (slow != fast) {
slow = slow->next;
fast = fast->next;
}

return slow;
}

so if we start moving both pointers again at the same speed such that one pointer (say slow) begins
from the head node of the linked list and other pointers (say fast) begins from the meeting point. When
the slow pointer reaches the beginning of the loop (has made m steps), the fast pointer would have
made also moved m steps as they are now moving the same pace. Since m+k is a multiple of n and fast
starts from k, they would meet at the beginning. Can they meet before also? No, because the slow
pointer enters the cycle first time after m steps.

Method 2:
this method, a temporary node is created. The next pointer of each node that is traversed is made to
point to this temporary node. This way we are using the next pointer of a node as a flag to indicate
whether the node has been traversed or not. Every node is checked to see if the next is pointing to a
temporary node or not. In the case of the first node of the loop, the second time we traverse it this
condition will be true, hence we return that node.
The code runs in O(n) time complexity and uses constant memory space.

// Function to detect first node of loop


// in a linked list that may contain loop
Node* detectLoop(Node* head)
{

// Create a temporary node


Node* temp = new Node;
while (head != NULL) {

// This condition is for the case


// when there is no loop
if (head->next == NULL) {
return NULL;
}

// Check if next is already


// pointing to temp
if (head->next == temp) {
break;
}

// Store the pointer to the next node


// in order to get to it in the next step
Node* nex = head->next;

// Make next point to temp


head->next = temp;

// Get to the next node in the list


head = nex;
}

return head;
}

We can also use the concept of hashing in order to detect the first node of the loop. The idea is simple
just iterate over the entire linked list and store node addresses in a set(C++ STL) one by one, while
adding the node address into the set check if it already contains that particular node address if not then
add node address to set if it is already present in the set then the current node is the first node of the
loop.

ListNode* detectCycle(ListNode* A)
{
// declaring map to store node address
unordered_set<ListNode*> uset;

ListNode *ptr = A;

// Default consider that no cycle is present


while (ptr != NULL) {

// checking if address is already present in map


if (uset.find(ptr) != uset.end())
return ptr;

// if address not present then insert into the set


else
uset.insert(ptr);

ptr = ptr->next;
}
return NULL;
}
6.Remove Duplicates in a sorted Linked List.

APPROACH : Traverse the list from the head (or start) node. While traversing, compare each node with
its next node. If the data of the next node is the same as the current node then delete the next node.
Before we delete a node, we need to store the next pointer of the node .

/* The function removes duplicates from a sorted list */


void removeDuplicates(Node* head)
{
/* Pointer to traverse the linked list */
Node* current = head;

/* Pointer to store the next pointer of a node to be deleted*/


Node* next_next;

/* do nothing if the list is empty */


if (current == NULL)
return;

/* Traverse the list till last node */


while (current->next != NULL)
{
/* Compare current node with next node */
if (current->data == current->next->data)
{
/* The sequence of steps is important*/
next_next = current->next->next;
free(current->next);
current->next = next_next;
}
else /* This is tricky: only advance if no deletion */
{
current = current->next;
}
}
}

Time Complexity: O(n) where n is the number of nodes in the given linked list.
/* The function removes duplicates
from a sorted list */

void removeDuplicates(Node* head)


{
/* Pointer to store the pointer of a node to be deleted*/
Node* to_free;

/* do nothing if the list is empty */


if (head == NULL)
return;

/* Traverse the list till last node */


if (head->next != NULL)
{

/* Compare head node with next node */


if (head->data == head->next->data)
{
/* The sequence of steps is important.
to_free pointer stores the next of head
pointer which is to be deleted.*/
to_free = head->next;
head->next = head->next->next;
free(to_free);
removeDuplicates(head);
}
else /* This is tricky: only
advance if no deletion */
{
removeDuplicates(head->next);
}
}
}

Using Map :
The idea is to push all the values in a map and printing its keys.

// Function to remove duplicates


void removeDuplicates(Node* head)
{
unordered_map<int, bool> track;
Node* temp = head;
while (temp) {
if (track.find(temp->data) == track.end()) {
cout << temp->data << " ";
}
track[temp->data] = true;
temp = temp->next;
}
}
Another Approach: Create a pointer that will point towards the first occurrence of every element and
another pointer temp which will iterate to every element and when the value of the previous pointer is
not equal to the temp pointer, we will set the pointer of the previous pointer to the first occurrence of
another node.

// Function to remove duplicates


// from the given linked list

Node *removeDuplicates(Node *head)


{

// Two references to head


// temp will iterate to the
// whole Linked List
// prev will point towards
// the first occurence of every element

Node *temp = head,*prev=head;

// Traverse list till the last node


while (temp != NULL)
{

// Compare values of both pointers


if(temp->data != prev->data)
{

/* if the value of prev is


not equal to the value of
temp that means there are no
more occurrences of the prev data->
So we can set the next of
prev to the temp node->*/

prev->next = temp;
prev = temp;
}

/*Set the temp to the next node*/

temp = temp->next;
}

/*This is the edge case if there


are more than one occurrences
of the last element*/
if(prev != temp)
{
prev->next = NULL;
}
return head;
}

7.Remove Duplicates in an Unsorted Linked List.

APPROACH :Using two loops


This is the simple way where two loops are used. Outer loop is used to pick the elements one by one
and the inner loop compares the picked element with the rest of the elements

/* Function to remove duplicates from a


unsorted linked list */
void removeDuplicates(struct Node* start)
{
struct Node *ptr1, *ptr2, *dup;
ptr1 = start;

/* Pick elements one by one */


while (ptr1 != NULL && ptr1->next != NULL) {
ptr2 = ptr1;

/* Compare the picked element with rest


of the elements */
while (ptr2->next != NULL) {
/* If duplicate then delete it */
if (ptr1->data == ptr2->next->data) {
/* sequence of steps is important here */
dup = ptr2->next;
ptr2->next = ptr2->next->next;
delete (dup);
}
else /* This is tricky */
ptr2 = ptr2->next;
}
ptr1 = ptr1->next;
}
}
Time Complexity: O(n^2)

METHOD 2 (Use Sorting)


In general, Merge Sort is the best-suited sorting algorithm for sorting linked lists efficiently.
1) Sort the elements using Merge Sort. note that this method doesn’t preserve the original order of
elements. Then follow removal of duplicates in sorted linked list manner
Time Complexity: O(nLogn)

METHOD 3 (Use Hashing)


We traverse the link list from head to end. For every newly encountered element, we check whether it is
in the hash table: if yes, we remove it; otherwise we put it in the hash table

Function to remove duplicates from a


unsorted linked list */
void removeDuplicates(struct Node *start)
{
// Hash to store seen values
unordered_set<int> seen;

/* Pick elements one by one */

struct Node *curr = start;


struct Node *prev = NULL;
while (curr != NULL)
{
// If current value is seen before
if (seen.find(curr->data) != seen.end())
{
prev->next = curr->next;
delete (curr);
}
else
{
seen.insert(curr->data);
prev = curr;
}
curr = prev->next;
}
}
Time Complexity: O(n) on average (assuming that hash table access time is O(1) on average).

8.Write a Program to Move the last element to Front in a Linked List.

Algorithm:
Traverse the list till last node. Use two pointers: one to store the address of last node and other for
address of second last node. After the end of loop do following operations.

i) Make second last as last (secLast->next = NULL).


ii) Set next of last as head (last->next = *head_ref).
iii) Make last as head ( *head_ref = las

* We are using a double pointer


head_ref here because we change
head of the linked list inside
this function.*/
void moveToFront(Node **head_ref)
{
/* If linked list is empty, or
it contains only one node,
then nothing needs to be done,
simply return */
if (*head_ref == NULL || (*head_ref)->next == NULL)
return;

/* Initialize second last


and last pointers */
Node *secLast = NULL;
Node *last = *head_ref;

/*After this loop secLast contains


address of second last node and
last contains address of last node in Linked List */
while (last->next != NULL)
{
secLast = last;
last = last->next;
}

/* Set the next of second last as NULL */


secLast->next = NULL;

/* Set next of last as head node */


last->next = *head_ref;

/* Change the head pointer


to point to last node now */
*head_ref = last;
}

9.Add “1” to a number represented as a Linked List.

Reverse given linked list. For example, 1-> 9-> 9 -> 9 is converted to 9-> 9 -> 9 ->1.

Start traversing linked list from leftmost node and add 1 to it. If there is a carry, move to the next
node. Keep moving to the next node while there is a carry.

Reverse modified linked list and return head.

/* Function to reverse the linked list */


Node *reverse(Node *head)
{
Node * prev = NULL;
Node * current = head;
Node * next;
while (current != NULL)
{
next = current->next;
current->next = prev;
prev = current;
current = next;
}
return prev;
}

/* Adds one to a linked lists and return the head


node of resultant list */

Node *addOneUtil(Node *head)


{
// res is head node of the resultant list
Node* res = head;

Node *temp, *prev = NULL;

int carry = 1, sum;

while (head != NULL) //while both lists exist


{
// Calculate value of next digit in resultant list.
// The next digit is sum of following things
// (i) Carry
// (ii) Next digit of head list (if there is a
// next digit)

sum = carry + head->data;

// update carry for next calculation

carry = (sum >= 10)? 1 : 0;

// update sum if it is greater than 10

sum = sum % 10;

// Create a new node with sum as data


head->data = sum;

// Move head and second pointers to next nodes


temp = head;
head = head->next;
}

// if some carry is still there, add a new node to


// result list.
if (carry > 0)
temp->next = newNode(carry);

// return head of the resultant list


return res;
}

// This function mainly uses addOneUtil().


Node* addOne(Node *head)
{
// Reverse linked list
head = reverse(head);

// Add one from left to right of reversed


// list
head = addOneUtil(head);

// Reverse the modified list


return reverse(head);
}

10.Add two numbers represented by linked lists.

traverse both lists and One by one pick nodes of both lists and add the values. If the sum is more than
10 then make carry as 1 and reduce the sum. If one list has more elements than the other then consider
the remaining values of this list as 0.

The steps are:

1. Traverse the two linked lists from start to end


2. Add the two digits each from respective linked lists.
3. If one of the lists has reached the end then take 0 as its digit.
4. Continue it until both the end of the lists.
5. If the sum of two digits is greater than 9 then set carry as 1 and the current digit as
sum % 10

* Adds contents of two linked lists and


return the head node of resultant list */

Node* addTwoLists(Node* first, Node* second)


{

// res is head node of the resultant list


Node* res = NULL;

Node *temp, *prev = NULL;

int carry = 0, sum;

// while both lists exist


while (first != NULL
|| second != NULL) {
// Calculate value of next
// digit in resultant list.
// The next digit is sum of
// following things
// (i) Carry
// (ii) Next digit of first
// list (if there is a next digit)
// (ii) Next digit of second
// list (if there is a next digit)

sum = carry + (first ? first->data : 0)


+ (second ? second->data : 0);

// update carry for next calulation


carry = (sum >= 10) ? 1 : 0;

// update sum if it is greater than 10


sum = sum % 10;

// Create a new node with sum as data


temp = newNode(sum);

// if this is the first node then


// set it as head of the resultant list

if (res == NULL)
res = temp;

// If this is not the first


// node then connect it to the rest.
else
prev->next = temp;

// Set prev for next insertion


prev = temp;

// Move first and second


// pointers to next nodes
if (first)
first = first->next;
if (second)
second = second->next;
}

if (carry > 0)
temp->next = newNode(carry);

// return head of the resultant list


return res;
}
Time Complexity: O(m + n), where m and n are numbers of nodes in first and second lists respectively.
The lists need to be traversed only once.
Space Complexity: O(m + n).
A temporary linked list is needed to store the output number
(Using STL): Using stack data structure

Create 3 stacks namely s1,s2,s3.

Fill s1 with Nodes of list1 and fill s2 with nodes of list2.

Fill s3 by creating new nodes and setting the data of new nodes to the sum of
s1.top(), s2.top() and carry until list1 and list2 are empty .

If the sum >9

set carry 1

else

set carry 0

Create a Node(say prev) that will contain the head of the sum List.

Link all the elements of s3 from top to bottom

return prev

/ function that returns the sum of two numbers represented


// by linked lists

Node* addTwoNumbers(Node* l1, Node* l2)


{
Node* prev = NULL;
// Create 3 stacks

stack<Node*> s1, s2, s3;


// Fill first stack with first List Elements

while (l1 != NULL) {


s1.push(l1);
l1 = l1->next;
}

// Fill second stack with second List Elements

while (l2 != NULL) {


s2.push(l2);
l2 = l2->next;
}

int carry = 0;
// Fill the third stack with the sum of first and second
// stack

while (!s1.empty() && !s2.empty())


{
int sum = s1.top()->data + s2.top()->data + carry;
Node* temp = newnode(sum % 10);
s3.push(temp);
if (sum > 9) {
carry = 1;
}
else {
carry = 0;
}
s1.pop();
s2.pop();
}

while (!s1.empty()) {
int sum = carry + s1.top()->data;
Node* temp = newnode(sum % 10);
s3.push(temp);
if (sum > 9) {
carry = 1;
}
else {
carry = 0;
}
s1.pop();
}
while (!s2.empty()) {
int sum = carry + s2.top()->data;
Node* temp = newnode(sum % 10);
s3.push(temp);
if (sum > 9)
{
carry = 1;
}
else {
carry = 0;
}
s2.pop();
}

// If carry is still present create a new node with


// value 1 and push it to the third stack

if (carry == 1) {
Node* temp = newnode(1);
s3.push(temp);
}

// Link all the elements inside third stack with each


// other

if (!s3.empty())
prev = s3.top();
while (!s3.empty()) {
Node* temp = s3.top();
s3.pop();
if (s3.size() == 0) {
temp->next = NULL;
}
else {
temp->next = s3.top();
}
}
return prev;
}

11.Intersection of two Sorted Linked List.

Method 1: Using Dummy Node.


Approach:
The idea is to use a temporary dummy node at the start of the result list. The pointer tail always points to
the last node in the result list, so new nodes can be added easily. The dummy node initially gives the tail
a memory space to point to. This dummy node is efficient, since it is only temporary, and it is allocated in
the stack. The loop proceeds, removing one node from either ‘a’ or ‘b’ and adding it to the tail. When the
given lists are traversed the result is in dummy. next, as the values are allocated from next node of the
dummy. If both the elements are equal then remove both and insert the element to the tail. Else remove
the smaller element among both the lists.

/*This solution uses the temporary


dummy to build up the result list */
Node* sortedIntersect(Node* a, Node* b)
{
Node dummy;
Node* tail = &dummy;
dummy.next = NULL;

/* Once one or the other


list runs out -- we're done */

while (a != NULL && b != NULL) {


if (a->data == b->data) {
push((&tail->next), a->data);
tail = tail->next;
a = a->next;
b = b->next;
}
/* advance the smaller list */
else if (a->data < b->data)
a = a->next;
else
b = b->next;
}
return (dummy.next);
}

time Complexity: O(m+n) where m and n are number of nodes in first and second linked
lists respectively.
Only one traversal of the lists are needed.

Auxiliary Space: O(min(m, n)).


The output list can store at most min(m,n) nodes .

Using Local References.


Approach: This solution is structurally very similar to the above, but it avoids using a
dummy node Instead, it maintains a struct node** pointer, lastPtrRef, that always points to
the last pointer of the result list. This solves the same case that the dummy node did —
dealing with the result list when it is empty. If the list is built at its tail, either the dummy node
or the struct node** “reference” strategy can be used.

* This solution uses the local reference */

struct Node* sortedIntersect


(
struct Node* a,
struct Node* b)
{
struct Node* result = NULL;

struct Node** lastPtrRef = &result;

/* Advance comparing the first


nodes in both lists.
When one or the other list runs
out, we're done. */

while (a != NULL && b != NULL)


{
if (a->data == b->data)
{
/* found a node for the intersection */

push(lastPtrRef, a->data);
lastPtrRef = &((*lastPtrRef)->next);
a = a->next;
b = b->next;
}
else if (a->data < b->data)
a = a->next; /* advance the smaller list */
else
b = b->next;
}
return (result);
}

Time Complexity: O(m+n) where m and n are number of nodes in first and second
linked lists respectively.
Only one traversal of the lists are needed.

Auxiliary Space: O(max(m, n)).


The output list can store at most m+n nodes.

Recursive Solution.

Approach:

The recursive approach is very similar to the the above two approaches. Build a
recursive function that takes two nodes and returns a linked list node. Compare the
first element of both the lists.
If they are similar then call the recursive function with the next node of both the lists.
Create a node with the data of the current node and put the returned node from the
recursive function to the next pointer of the node created. Return the node created.

If the values are not equal then remove the smaller node of both the lists and call the
recursive function.

struct Node* sortedIntersect(struct Node* a,


struct Node* b)
{

// base case
if (a == NULL || b == NULL)
return NULL;

/* If both lists are non-empty */

/* Advance the smaller list and


call recursively */
if (a->data < b->data)
return sortedIntersect(a->next, b);

if (a->data > b->data)


return sortedIntersect(a, b->next);

// Below lines are executed only


// when a->data == b->data
struct Node* temp = (struct Node*)malloc(
sizeof(struct Node));
temp->data = a->data;

// Advance both lists and call recursively


temp->next = sortedIntersect(a->next,
b->next);
return temp;
}
Time Complexity: O(m+n) where m and n are number of nodes in first and second
linked lists respectively.
Only one traversal of the lists are needed.

Auxiliary Space: O(max(m, n)).


The output list can store at most m+n nodes.

12.Intersection Point of two Linked Lists.

Method 1(Simply use two loops)

Use 2 nested for loops. The outer loop will be for each node of the 1st list and inner loop will be for
the 2nd list. In the inner loop, check if any of the nodes of the 2nd list is the same as the current
node of the first linked list. The time complexity of this method will be O(M * N) where m and n are
the numbers of nodes in two lists.

Method 2

Mark Visited Nodes)


This solution requires modifications to basic linked list data structure. Have a visited flag with each
node. Traverse the first linked list and keep marking visited nodes. Now traverse the second linked
list, If you see a visited node again then there is an intersection point, return the intersecting node.
This solution works in O(m+n) but requires additional information with each node. A variation of this
solution that doesn’t require modification to the basic data structure can be implemented using a
hash. Traverse the first linked list and store the addresses of visited nodes in a hash. Now traverse
the second linked list and if you see an address that already exists in the hash then return the
intersecting node.

Using difference of node counts

Get count of the nodes in the first list, let count be c1.

Get count of the nodes in the second list, let count be c2.

Get the difference of counts d = abs(c1 – c2 .

Now traverse the bigger list from the first node till d nodes so that from here onwards both the lists
have equal no of nodes .Then we can traverse both the lists in parallel till we come across a
common node. (Note that getting a common node is done by comparing the address of the nodes)

/* function to get the intersection point of two linked


lists head1 and head2 */

int getIntesectionNode(Node* head1, Node* head2)


{

// Count the number of nodes in


// both the linked list
int c1 = getCount(head1);
int c2 = getCount(head2);
int d;

// If first is greater
if (c1 > c2) {
d = c1 - c2;
return _getIntesectionNode(d, head1, head2);
}
else {
d = c2 - c1;
return _getIntesectionNode(d, head2, head1);
}
}

/* function to get the intersection point of two linked


lists head1 and head2 where head1 has d more nodes than
head2 */
int _getIntesectionNode(int d, Node* head1, Node* head2)
{
// Stand at the starting of the bigger list
Node* current1 = head1;
Node* current2 = head2;
// Move the pointer forward
for (int i = 0; i < d; i++) {
if (current1 == NULL) {
return -1;
}
current1 = current1->next;
}

// Move both pointers of both list till they


// intersect with each other
while (current1 != NULL && current2 != NULL) {
if (current1 == current2)
return current1->data;

// Move both the pointers forward


current1 = current1->next;
current2 = current2->next;
}

return -1;
}

/* Takes head pointer of the linked list and


returns the count of nodes in the list */
int getCount(Node* head)
{
Node* current = head;

// Counter to store count of nodes


int count = 0;

// Iterate till NULL


while (current != NULL) {

// Increase the counter


count++;

// Move the Node ahead


current = current->next;
}

return count;
}

(Use Hashing)
Basically, we need to find a common node of two linked lists. So we hash all nodes of the first list
and then check the second list.
1) Create an empty hash set.
2) Traverse the first linked list and insert all nodes’ addresses in the hash set.
3) Traverse the second list. For every node check if it is present in the hash set. If we find a node in
the hash set, return the node.
13.Merge Sort For Linked lists.[Very Important]

This approach is simpler and uses log n space.

mergeSort():

1. If the size of the linked list is 1 then return the head


2. Find mid using The Tortoise and The Hare Approach
3. Store the next of mid in head2 i.e. the right sub-linked list.
4. Now Make the next midpoint null.
5. Recursively call mergeSort() on both left and right sub-linked list and store the new
head of the left and right linked list.
6. Call merge() given the arguments new heads of left and right sub-linked lists and
store the final head returned after merging.
7. Return the final head of the merged linkedlist.

merge(head1, head2):

1. Take a pointer say merged to store the merged list in it and store a dummy node in it.
2. Take a pointer temp and assign merge to it.
3. If the data of head1 is less than the data of head2, then, store head1 in next of temp
& move head1 to the next of head1.
4. Else store head2 in next of temp & move head2 to the next of head2.
5. Move temp to the next of temp.
6. Repeat steps 3, 4 & 5 until head1 is not equal to null and head2 is not equal to null.
7. Now add any remaining nodes of the first or the second linked list to the merged
linked list.
8. Return the next of merged(that will ignore the dummy and return the head of the final
merged linked list)

14.Quicksort for Linked Lists.[Very Important]

15.Find the middle Element of a linked list.

Method 1:
Traverse the whole linked list and count the no. of nodes. Now traverse the list again till count/2 and
return the node at count/2.
Method 2:

Traverse linked list using two pointers. Move one pointer by one and the other pointers by two. When the
fast pointer reaches the end slow pointer will reach the middle of the linked list.

void printMiddle(class Node *head){


struct Node *slow_ptr = head;
struct Node *fast_ptr = head;

if (head!=NULL)
{
while (fast_ptr != NULL && fast_ptr->next != NULL)
{
fast_ptr = fast_ptr->next->next;
slow_ptr = slow_ptr->next;
}
cout << "The middle element is [" << slow_ptr->data << "]" << endl;
}
}

16.Check if a linked list is a circular linked list.

The idea is to store head of the linked list and traverse it. If we reach NULL, linked list is not circular. If
reach head again, linked list is circular.

/* This function returns true if given linked


list is circular, else false. */
bool isCircular(struct Node *head)
{
// An empty linked list is circular
if (head == NULL)
return true;

// Next of head
struct Node *node = head->next;

// This loop would stop in both cases (1) If


// Circular (2) Not circular
while (node != NULL && node != head)
node = node->next;

// If loop stopped because of circular


// condition
return (node == head);
}

17.Split a Circular linked list into two halves.

APPROACH:

1) Store the mid and last pointers of the circular linked list using tortoise and hare algorithm.
2) Make the second half circular.
3) Make the first half circular.
4) Set head (or start) pointers of the two linked lists.
In the below implementation, if there are odd nodes in the given circular linked list then the first result list
has 1 more node than the second result list.

Function to split a list (starting with head)


into two lists. head1_ref and head2_ref are
references to head nodes of the two resultant
linked lists */
void splitList(Node *head, Node **head1_ref,
Node **head2_ref)
{
Node *slow_ptr = head;
Node *fast_ptr = head;

if(head == NULL)
return;
/* If there are odd nodes in the circular list then
fast_ptr->next becomes head and for even nodes
fast_ptr->next->next becomes head */

while(fast_ptr->next != head &&


fast_ptr->next->next != head)
{
fast_ptr = fast_ptr->next->next;
slow_ptr = slow_ptr->next;
}

/* If there are even elements in list


then move fast_ptr */
if(fast_ptr->next->next == head)
fast_ptr = fast_ptr->next;

/* Set the head pointer of first half */


*head1_ref = head;

/* Set the head pointer of second half */


if(head->next != head)
*head2_ref = slow_ptr->next;

/* Make second half circular */


fast_ptr->next = slow_ptr->next;

/* Make first half circular */


slow_ptr->next = head;
}

Time Complexity: O(n)

18.Write a Program to check whether the Singly Linked list is a palindrome or not. .

METHOD 1 (Use a Stack)


A simple solution is to use a stack of list nodes.
This mainly involves three steps.
Traverse the given list from head to tail and push every visited node to stack.
Traverse the list again. For every visited node, pop a node from the stack and compare data of popped
node with the currently visited node.
If all nodes matched, then return true, else false.

/ Function to check if the linked list


// is palindrome or not

bool isPalin(Node* head){

// Temp pointer
Node* slow= head;

// Declare a stack
stack <int> s;

// Push all elements of the list


// to the stack
while(slow != NULL){
s.push(slow->data);

// Move ahead
slow = slow->ptr;
}

// Iterate in the list again and


// check by popping from the stack
while(head != NULL ){

// Get the top most element


int i=s.top();

// Pop the element


s.pop();

// Check if data is not


// same as popped element
if(head -> data != i){
return false;
}

// Move ahead
head=head->ptr;
}

return true;
}

(By reversing the list)

This method takes O(n) time and O(1) extra space.


1) Get the middle of the linked list.
2) Reverse the second half of the linked list.
3) Check if the first half and second half are identical.
4) Construct the original linked list by reversing the second half again and attaching it back to the first
half

When a number of nodes are even, the first and second half contain exactly half nodes. The challenging
thing in this method is to handle the case when the number of nodes is odd. We don’t want the middle
node as part of the lists as we are going to compare them for equality. For odd cases, we use a separate
variable ‘midnode’.

// Function to check if given linked list is


// palindrome or not

bool isPalindrome(struct Node* head)


{
struct Node *slow_ptr = head, *fast_ptr = head;
struct Node *second_half, *prev_of_slow_ptr = head;

// To handle odd size list


struct Node* midnode = NULL;

// initialize result
bool res = true;
if (head != NULL && head->next != NULL)
{

// Get the middle of the list. Move slow_ptr by 1


// and fast_ptrr by 2, slow_ptr will have the middle
// node
while (fast_ptr != NULL && fast_ptr->next != NULL)
{
fast_ptr = fast_ptr->next->next;

// We need previous of the slow_ptr for


// linked lists with odd elements
prev_of_slow_ptr = slow_ptr;
slow_ptr = slow_ptr->next;
}

// fast_ptr would become NULL when there


// are even elements in list. And not NULL
// for odd elements. We need to skip the
// middle node for odd case and store it
// somewhere so that we can restore the
// original list

if (fast_ptr != NULL)
{
midnode = slow_ptr;
slow_ptr = slow_ptr->next;
}

// Now reverse the second half and


// compare it with first half
second_half = slow_ptr;

// NULL terminate first half


prev_of_slow_ptr->next = NULL;

// Reverse the second half


reverse(&second_half);

// compare
res = compareLists(head, second_half);

// Construct the original list back


reverse(&second_half); // Reverse the second half again

// If there was a mid node (odd size case)


// which was not part of either first half
// or second half.

if (midnode != NULL)
{
prev_of_slow_ptr->next = midnode;
midnode->next = second_half;
}
else
prev_of_slow_ptr->next = second_half;
}
return res;
}

// Function to reverse the linked list


// Note that this function may change
// the head

void reverse(struct Node** head_ref)


{
struct Node* prev = NULL;
struct Node* current = *head_ref;
struct Node* next;

while (current != NULL)


{
next = current->next;
current->next = prev;
prev = current;
current = next;
}
*head_ref = prev;
}

// Function to check if two input


// lists have same data

bool compareLists(struct Node* head1,


struct Node* head2)
{
struct Node* temp1 = head1;
struct Node* temp2 = head2;

while (temp1 && temp2)


{
if (temp1->data == temp2->data)
{
temp1 = temp1->next;
temp2 = temp2->next;
}
else
return 0;
}

// Both are empty reurn 1


if (temp1 == NULL && temp2 == NULL)
return 1;

// Will reach here when one is NULL


// and other is not
return 0;
}
Time Complexity: O(n)

Auxiliary Space: O(1)


Use two pointers left and right. Move right and left using recursion and check for following in each
recursive call.
1) Sub-list is a palindrome.
2) Value at current left and right are matching.

If both above conditions are true then return true.

The idea is to use function call stack as a container. Recursively traverse till the end of list.
When we return from last NULL, we will be at the last node. The last node to be compared
with first node of list.

In order to access first node of list, we need list head to be available in the last call of recursion. Hence,
we pass head also to the recursive function. If they both match we need to compare (2, n-2) nodes.
Again when recursion falls back to (n-2)nd node, we need reference to 2nd node from the head. We
advance the head pointer in the previous call, to refer to the next node in the list.
However, the trick is identifying a double-pointer. Passing a single pointer is as good as pass-by-value,
and we will pass the same pointer again and again. We need to pass the address of the head pointer for
reflecting the changes in parent recursive calls.

// Initial parameters to this function are &head and head

bool isPalindromeUtil(struct node** left, struct node* right)


{
/* stop recursion when right becomes NULL */
if (right == NULL)
return true;

/* If sub-list is not palindrome then no need to


check for current left and right, return false */

bool isp = isPalindromeUtil(left, right->next);


if (isp == false)
return false;

/* Check values at current left and right */


bool isp1 = (right->data == (*left)->data);

/* Move left to next node */


*left = (*left)->next;

return isp1;
}
// A wrapper over isPalindromeUtil()
bool isPalindrome(struct node* head)
{
isPalindromeUtil(&head, head);
}

19.Deletion from a Circular Linked List.

Algorithm

Case 1: List is empty.

If the list is empty we will simply return.

Case 2:List is not empty


If the list is not empty then we define two pointers curr and prev and initialize the
pointer curr with the head node.

Traverse the list using curr to find the node to be deleted and before moving to curr
to the next node, every time set prev = curr.

If the node is found, check if it is the only node in the list. If yes, set head = NULL and
free(curr).

If the list has more than one node, check if it is the first node of the list. Condition to
check this( curr == head). If yes, then move prev until it reaches the last node. After
prev reaches the last node, set head = head -> next and prev -> next = head. Delete
curr.

If curr is not the first node, we check if it is the last node in the list. Condition to check
this is (curr -> next == head).

If curr is the last node. Set prev -> next = head and delete the node curr by free(curr).

If the node to be deleted is neither the first node nor the last node, then set prev ->
next = curr -> next and delete curr.

/* Function to delete a given node from the list */


void deleteNode(Node** head, int key)
{

// If linked list is empty


if (*head == NULL)
return;

// If the list contains only a single node


if((*head)->data==key && (*head)->next==*head)
{
free(*head);
*head=NULL;
return;
}

Node *last=*head,*d;

// If head is to be deleted
if((*head)->data==key)
{

// Find the last node of the list


while(last->next!=*head)
last=last->next;

// Point last node to the next of head i.e.


// the second node of the list
last->next=(*head)->next;
free(*head);
*head=last->next;
}

// Either the node to be deleted is not found


// or the end of list is not reached
while(last->next!=*head&&last->next->data!=key)
{
last=last->next;
}

// If node to be deleted was found


if(last->next->data==key)
{
d=last->next;
last->next=d->next;
free(d);
}
else
cout<<"no such keyfound";
}

20.Reverse a Doubly Linked list.

Here is a simple method for reversing a Doubly Linked List. All we need to do is swap prev and next
pointers for all nodes, change prev of the head (or start) and change the head pointer in the end.
* Function to reverse a Doubly Linked List */
void reverse(Node **head_ref)
{
Node *temp = NULL;
Node *current = *head_ref;

/* swap next and prev for all nodes of


doubly linked list */
while (current != NULL)
{
temp = current->prev;
current->prev = current->next;
current->next = temp;
current = current->prev;
}

/* Before changing the head, check for the cases like empty
list and list with only one node */
if(temp != NULL )
*head_ref = temp->prev;
}
Time Complexity: O(N), where N denotes the number of nodes in the doubly linked list.
Auxiliary Space: O(1)

We can also swap data instead of pointers to reverse the Doubly Linked List. Method used for reversing
array can be used to swap data. Swapping data can be costly compared to pointers if the size of the
data item(s) is more.

Method 2:

The same question can also be done by using Stacks.

Steps:
1. Keep pushing the node’s data in the stack. -> O(n)
2. The keep popping the elements out and updating the Doubly Linked List

* Function to reverse a Doubly Linked List using Stacks

* Function to reverse a Doubly Linked List using Stacks


*/
void reverse()
{
stack<int> st;
Node* temp = head;
while (temp != NULL) {
st.push(temp->data);
temp = temp->next;
}

// added all the elements sequemce wise in the


// st
temp = head;
while (temp != NULL) {
temp->data = st.top();
st.pop();
temp = temp->next;
}

// popped all the elements and the added in the


// linked list,
// which are in the reversed order->
}
Time Complexity: O(N)

Auxiliary Space: O(N)

In this method, we traverse the linked list once and add elements to the stack, and
again traverse the whole for updating all the elements. The whole takes 2n time,
which is the time complexity of O(n)

21.Find pairs with a given sum in a DLL.

Given a sorted doubly linked list of positive distinct elements, the task is to find pairs in a doubly-linked
list whose sum is equal to given value x, without using any extra space?

A simple approach for this problem is to one by one pick each node and find a second element whose
sum is equal to x in the remaining list by traversing in the forward direction. The time complexity for this
problem will be O(n^2), n is the total number of nodes in the doubly linked list.

● Initialize two pointer variables to find the candidate elements in the sorted doubly
linked list. Initialize first with the start of the doubly linked list i.e; first=head and
initialize second with the last node of the doubly linked list i.e; second=last_node.
● We initialize first and second pointers as first and last nodes. Here we don’t have
random access, so to find the second pointer, we traverse the list to initialize the
second.
● If current sum of first and second is less than x, then we move first in forward
direction. If current sum of first and second element is greater than x, then we move
second in backward direction.
● Loop termination conditions are also different from arrays. The loop terminates when
two pointers cross each other (second->next = first), or they become the same (first
== second).
● The case when no pairs are present will be handled by the condition “first==second”

// Function to find pair whose sum equal to given value x.


void pairSum(struct Node *head, int x)
{
// Set two pointers, first to the beginning of DLL
// and second to the end of DLL.
struct Node *first = head;
struct Node *second = head;
while (second->next != NULL)
second = second->next;

// To track if we find a pair or not


bool found = false;

// The loop terminates when two pointers


// cross each other (second->next
// == first), or they become same (first == second)
while (first != second && second->next != first)
{
// pair found
if ((first->data + second->data) == x)
{
found = true;
cout << "(" << first->data<< ", "
<< second->data << ")" << endl;

// move first in forward direction


first = first->next;

// move second in backward direction


second = second->prev;
}
else
{
if ((first->data + second->data) < x)
first = first->next;
else
second = second->prev;
}
}

// if pair is not present


if (found == false)
cout << "No pair found";
}
Time complexity : O(n)

Auxiliary space : O(1)

If linked list is not sorted, then we can sort the list as a first step. But in that case overall time complexity
would become O(n Log n). We can use Hashing in such cases if extra space is not a constraint.
22.Count triplets in a sorted DLL whose sum is equal to given value “X”.

Method 1 (Naive Approach):


Using three nested loops generate all triplets and check whether elements in the triplet sum up to x or
not.

// function to count triplets in a sorted doubly linked list


// whose sum is equal to a given value 'x'
int countTriplets(struct Node* head, int x)
{
struct Node* ptr1, *ptr2, *ptr3;
int count = 0;

// generate all possible triplets


for (ptr1 = head; ptr1 != NULL; ptr1 = ptr1->next)
for (ptr2 = ptr1->next; ptr2 != NULL; ptr2 = ptr2->next)
for (ptr3 = ptr2->next; ptr3 != NULL; ptr3 = ptr3->next)

// if elements in the current triplet sum up to 'x'


if ((ptr1->data + ptr2->data + ptr3->data) == x)

// increment count
count++;

// required count of triplets


return count;
}
Time Complexity: O(n3)
Auxiliary Space: O(1)

Efficient Approach(Use of two pointers):


Traverse the doubly linked list from left to right. For each current node during the traversal, initialize two
pointers first = pointer to the node next to the current node and last = pointer to the last node of the list.
Now, count pairs in the list from first to last pointer that sum up to value (x – current node’s data)
(algorithm described in this post). Add this count to the total_count of triplets. Pointer to the last node
can be found only once in the beginning.

// function to count pairs whose sum equal to given 'value'


int countPairs(struct Node* first, struct Node* second, int value)
{
int count = 0;

// The loop terminates when either of two pointers


// become NULL, or they cross each other (second->next
// == first), or they become same (first == second)
while (first != NULL && second != NULL &&
first != second && second->next != first) {

// pair found
if ((first->data + second->data) == value) {

// increment count
count++;

// move first in forward direction


first = first->next;

// move second in backward direction


second = second->prev;
}

// if sum is greater than 'value'


// move second in backward direction
else if ((first->data + second->data) > value)
second = second->prev;

// else move first in forward direction


else
first = first->next;
}

// required count of pairs


return count;
}

// function to count triplets in a sorted doubly linked list


// whose sum is equal to a given value 'x'
int countTriplets(struct Node* head, int x)
{
// if list is empty
if (head == NULL)
return 0;

struct Node* current, *first, *last;


int count = 0;

// get pointer to the last node of


// the doubly linked list
last = head;
while (last->next != NULL)
last = last->next;

// traversing the doubly linked list


for (current = head; current != NULL; current = current->next) {

// for each current node


first = current->next;

// count pairs with sum(x - current->data) in the range


// first to last and add it to the 'count' of triplets
count += countPairs(first, last, x - current->data);
}

// required count of triplets


return count;
}
Time Complexity: O(n2)
Auxiliary Space: O(1)
23.Sort a “k”sorted Doubly Linked list.[Very IMP]

Sort the given doubly linked list using the insertion sort technique. While inserting each element in the
sorted part of the list, there will be at most k swaps to place the element to its correct position since it is
at most k steps away from its correct position.

/ function to sort a k sorted doubly linked list

struct Node* sortAKSortedDLL(struct Node* head, int k)


{
if(head == NULL || head->next == NULL)
return head;

// perform on all the nodes in list


for(Node *i = head->next; i != NULL; i = i->next) {
Node *j = i;

// There will be atmost k swaps for each element in the list


// since each node is k steps away from its correct position
while(j->prev != NULL && j->data < j->prev->data) {
// swap j and j.prev node
Node* temp = j->prev->prev;
Node* temp2 = j->prev;
Node *temp3 = j->next;
j->prev->next = temp3;
j->prev->prev = j;
j->prev = temp;
j->next = temp2;
if(temp != NULL)
temp->next = j;
if(temp3 != NULL)
temp3->prev = temp2;
}
// if j is now the new head
// then reset head
if(j->prev == NULL)
head = j;
}
return head;
}
Time Complexity: O(n*k)
Auxiliary Space: O(1)

Efficient Approach: We can sort the list using the MIN HEAP data structure. The approach has been
explained in Sort a nearly sorted (or K sorted) array. We only have to be careful while traversing the
input doubly linked list and adjusting the required next and previous links in the final sorted list.

// 'compare' function used to build up the


// priority queue
struct compare {
bool operator()(struct Node* p1, struct Node* p2)
{
return p1->data > p2->data;
}
};

// function to sort a k sorted doubly linked list


struct Node* sortAKSortedDLL(struct Node* head, int k)
{
// if list is empty
if (head == NULL)
return head;

// priority_queue 'pq' implemented as min heap with the


// help of 'compare' function
priority_queue<Node*, vector<Node*>, compare> pq;

struct Node* newHead = NULL, *last;

// Create a Min Heap of first (k+1) elements from


// input doubly linked list
for (int i = 0; head != NULL && i <= k; i++) {
// push the node on to 'pq'
pq.push(head);

// move to the next node


head = head->next;
}

// loop till there are elements in 'pq'


while (!pq.empty()) {

// place root or top of 'pq' at the end of the


// result sorted list so far having the first node
// pointed to by 'newHead'
// and adjust the required links

if (newHead == NULL) {
newHead = pq.top();
newHead->prev = NULL;

// 'last' points to the last node


// of the result sorted list so far
last = newHead;
}

else {
last->next = pq.top();
pq.top()->prev = last;
last = pq.top();
}

// remove element from 'pq'


pq.pop();

// if there are more nodes left in the input list


if (head != NULL) {
// push the node on to 'pq'
pq.push(head);
// move to the next node
head = head->next;
}
}

// making 'next' of last node point to NULL


last->next = NULL;

// new head of the required sorted DLL


return newHead;
Time Complexity: O(n*log k)
Auxiliary Space: O(k

25.Rotate a Doubly Linked list in a group of Given Size.[Very IMP]

Create a recursive function, say reverse(head, k). This function receives the head or the first node of
each group of k nodes. It reverses those group of k nodes . After reversing the group of k nodes the
function checks whether next group of nodes exists in the list or not. If group exists then it makes a
recursive call to itself with the first node of the next group and makes the necessary adjustments with
the next and previous links of that group. Finally it returns the new head node of the reversed group.

// function to reverse a doubly linked list


// in groups of given size
Node* revListInGroupOfGivenSize(Node* head, int k)
{
Node *current = head;
Node* next = NULL;
Node* newHead = NULL;
int count = 0;

// reversing the current group of k


// or less than k nodes by adding
// them at the beginning of list
// 'newHead'
while (current != NULL && count < k)
{
next = current->next;
push(&newHead, current);
current = next;
count++;
}

// if next group exists then making the desired


// adjustments in the link
if (next != NULL)
{
head->next = revListInGroupOfGivenSize(next, k);
head->next->prev = head;
}

// pointer to the new head of the


// reversed group
return newHead;
}
Time Complexity: O(n).

26.Flatten a Linked List

Given a linked list where every node represents a linked list and contains two pointers of its type:
(i) Pointer to next node in the main list (we call it ‘right’ pointer in the code below)
(ii) Pointer to a linked list where this node is headed

The idea is to use the Merge() process of merge sort for linked lists. We use merge() to merge lists one
by one. We recursively merge() the current list with the already flattened list.
The down pointer is used to link nodes of the flattened list.

// An utility function to merge two sorted linked lists


Node merge(Node a, Node b)
{
// if first linked list is empty then second
// is the answer
if (a == null) return b;

// if second linked list is empty then first


// is the result
if (b == null) return a;

// compare the data members of the two linked lists


// and put the larger one in the result
Node result;

if (a.data < b.data)


{
result = a;
result.down = merge(a.down, b);
}

else
{
result = b;
result.down = merge(a, b.down);
}

result.right = null;
return result;
}

Node flatten(Node root)


{
// Base Cases
if (root == null || root.right == null)
return root;

// recur for list on right


root.right = flatten(root.right);

// now merge
root = merge(root, root.right);

// return the root


// it will be in turn merged with its left
return root;
}

27.Sort a LL of 0's, 1's and 2's

Following steps can be used to sort the given linked list.

Traverse the list and count the number of 0s, 1s, and 2s. Let the counts be n1, n2, and n3
respectively.

Traverse the list again, fill the first n1 nodes with 0, then n2 nodes with 1, and finally n3
nodes with 2.

// Function to sort a linked list of 0s, 1s and 2s


void sortList(Node *head)
{
int count[3] = {0, 0, 0}; // Initialize count of '0', '1' and '2' as 0
Node *ptr = head;

/* count total number of '0', '1' and '2'


* count[0] will store total number of '0's
* count[1] will store total number of '1's
* count[2] will store total number of '2's */
while (ptr != NULL)
{
count[ptr->data] += 1;
ptr = ptr->next;
}

int i = 0;
ptr = head;

/* Let say count[0] = n1, count[1] = n2 and count[2] = n3


* now start traversing list from head node,
* 1) fill the list with 0, till n1 > 0
* 2) fill the list with 1, till n2 > 0
* 3) fill the list with 2, till n3 > 0 */
while (ptr != NULL)
{
if (count[i] == 0)
++i;
else
{
ptr->data = i;
--count[i];
ptr = ptr->next;
}
}
}
Time Complexity: O(n) where n is the number of nodes in the linked list.
Auxiliary Space: O(1)

28.Clone a linked list with next and random pointer

Below is the Algorithm:

● Create the copy of node 1 and insert it between node 1 & node 2 in the original
Linked List, create a copy of 2 and insert it between 2 & 3. Continue in this fashion,
add the copy of N after the Nth node

● Now copy the random link in this fashion

original->next->random= original->random->next; /*TRAVERSE


TWO NODES*/

● This works because original->next is nothing but a copy of the original and
Original->random->next is nothing but a copy of the random.

● Now restore the original and copy linked lists in this fashion in a single loop.

original->next = original->next->next;
copy->next = copy->next->next;

● Ensure that original->next is NULL and return the cloned list

/ This function clones a given linked list


// in O(1) space
Node* clone(Node *start)
{
Node* curr = start, *temp;

// insert additional node after


// every node of original list
while (curr)
{
temp = curr->next;

// Inserting node
curr->next = new Node(curr->data);
curr->next->next = temp;
curr = temp;
}

curr = start;

// adjust the random pointers of the


// newly added nodes
while (curr)
{
if(curr->next)
curr->next->random = curr->random ?
curr->random->next : curr->random;
// move to the next newly added node by
// skipping an original node
curr = curr->next?curr->next->next:curr->next;
}

Node* original = start, *copy = start->next;

// save the start of copied linked list


temp = copy;

// now separate the original list and copied list


while (original && copy)
{
original->next =
original->next? original->next->next : original->next;

copy->next = copy->next?copy->next->next:copy->next;
original = original->next;
copy = copy->next;
}

return temp;
}

29.Merge K sorted Linked list

Method 1 (Simple)

Approach:

A Simple Solution is to initialize the result as the first list. Now traverse all lists starting from
the second list. Insert every node of the currently traversed list into result in a sorted way.

The main function that


// takes an array of lists
// arr[0..last] and generates
// the sorted output
Node* mergeKLists(Node* arr[], int last)
{

// Traverse form second list to last


for (int i = 1; i <= last; i++) {
while (true) {
// head of both the lists,
// 0 and ith list.
Node *head_0 = arr[0], *head_i = arr[i];

// Break if list ended


if (head_i == NULL)
break;

// Smaller than first element


if (head_0->data >= head_i->data) {
arr[i] = head_i->next;
head_i->next = head_0;
arr[0] = head_i;
}
else
// Traverse the first list
while (head_0->next != NULL) {
// Smaller than next element
if (head_0->next->data
>= head_i->data) {
arr[i] = head_i->next;
head_i->next = head_0->next;
head_0->next = head_i;
break;
}
// go to next node
head_0 = head_0->next;

// if last node
if (head_0->next == NULL) {
arr[i] = head_i->next;
head_i->next = NULL;
head_0->next = head_i;
head_0->next->next = NULL;
break;
}
}
}
}

return arr[0];
}
● Time complexity: O(nk2)
● Auxiliary Space: O(1).
As no extra space is required

in this post, Divide and Conquer approach is discussed. This approach doesn’t require
extra space for heap and works in O(nk Log k)
It is known that merging of two linked lists can be done in O(n) time and O(n) space.

1. The idea is to pair up K lists and merge each pair in linear time using O(n) space.
2. After the first cycle, K/2 lists are left each of size 2*N. After the second cycle, K/4 lists
are left each of size 4*N and so on.
3. Repeat the procedure until we have only one list left.

Takes two lists sorted in increasing order, and merge


their nodes together to make one big sorted list. Below
function takes O(n) extra space for recursive calls,
*/
Node* SortedMerge(Node* a, Node* b)
{
Node* result = NULL;

/* Base cases */
if (a == NULL)
return (b);
else if (b == NULL)
return (a);

/* Pick either a or b, and recur */


if (a->data <= b->data) {
result = a;
result->next = SortedMerge(a->next, b);
}
else {
result = b;
result->next = SortedMerge(a, b->next);
}

return result;
}

// The main function that takes an array of lists


// arr[0..last] and generates the sorted output
Node* mergeKLists(Node* arr[], int last)
{
// repeat until only one list is left
while (last != 0) {
int i = 0, j = last;

// (i, j) forms a pair


while (i < j) {
// merge List i with List j and store
// merged list in List i
arr[i] = SortedMerge(arr[i], arr[j]);

// consider next pair


i++, j--;

// If all pairs are merged, update last


if (i >= j)
last = j;
}
}

return arr[0];
}

30.Multiply 2 no. represented by LL

Reverse both linked lists


Make a linked list of maximum result size (m + n + 1)
For each node of one list
For each node of second list
a) Multiply nodes
b) Add digit in result LL at corresponding
position
c) Now resultant node itself can be higher
than one digit
d) Make carry for next node
Leave one last column means next time start
From next node in result list
Reverse the resulted linked list

// Function to reverse the linked list and return


// its length
int reverse(struct Node** head_ref)
{
struct Node* prev = NULL;
struct Node* current = *head_ref;
struct Node* next;
int len = 0;
while (current != NULL) {
len++;
next = current->next;
current->next = prev;
prev = current;
current = next;
}
*head_ref = prev;
return len;
}

// Function to make an empty linked list of


// given size
struct Node* make_empty_list(int size)
{
struct Node* head = NULL;
while (size--)
push(&head, 0);
return head;
}

// Multiply contents of two linked lists => store


// in another list and return its head
struct Node* multiplyTwoLists(struct Node* first,
struct Node* second)
{
// reverse the lists to muliply from end
// m and n lengths of linked lists to make
// and empty list
int m = reverse(&first), n = reverse(&second);

// make a list that will contain the result


// of multiplication.
// m+n+1 can be max size of the list
struct Node* result = make_empty_list(m + n + 1);

// pointers for traverse linked lists and also


// to reverse them after
struct Node *second_ptr = second,
*result_ptr1 = result, *result_ptr2, *first_ptr;

// multiply each Node of second list with first


while (second_ptr) {
int carry = 0;

// each time we start from the next of Node


// from which we started last time
result_ptr2 = result_ptr1;

first_ptr = first;

while (first_ptr) {

// multiply a first list's digit with a


// current second list's digit
int mul = first_ptr->data * second_ptr->data
+ carry;

// Assigne the product to corresponding Node


// of result
result_ptr2->data += mul % 10;

// now resultant Node itself can have more


// than 1 digit
carry = mul / 10 + result_ptr2->data / 10;
result_ptr2->data = result_ptr2->data % 10;

first_ptr = first_ptr->next;
result_ptr2 = result_ptr2->next;
}

// if carry is remaining from last multiplication


if (carry > 0) {
result_ptr2->data += carry;
}

result_ptr1 = result_ptr1->next;
second_ptr = second_ptr->next;
}

// reverse the result_list as it was populated


// from last Node
reverse(&result);
reverse(&first);
reverse(&second);

// remove if there are zeros at starting


while (result->data == 0) {
struct Node* temp = result;
result = result->next;
free(temp);
}

// Return head of multiplication list


return result;
}
Note: we can take care of resultant node that can have more than 1 digit outside the loop just traverse
the result list and add carry to next digit before reversing.
31.Delete nodes which have a greater value on right side

Method 1 (Simple)
Use two loops. In the outer loop, pick nodes of the linked list one by one. In the inner loop, check if there
exists a node whose value is greater than the picked node. If there exists a node whose value is greater,
then delete the picked node.
Time Complexity: O(n^2)
Method 2 (Use Reverse)

1. Reverse the list.


2. Traverse the reversed list. Keep max till now. If the next node is less than max, then delete the next
node, otherwise max = next node.
3. Reverse the list again to retain the original order.
Time Complexity: O(n)

/* Deletes nodes which have a node with


greater value node on left side */
void delLesserNodes(struct Node** head_ref)
{
/* 1) Reverse the linked list */
reverseList(head_ref);

/* 2) In the reversed list, delete nodes


which have a node with greater value node
on left side. Note that head node is never
deleted because it is the leftmost node.*/
_delLesserNodes(*head_ref);

/* 3) Reverse the linked list again to


retain the original order */
reverseList(head_ref);
}

/* Deletes nodes which have


greater value node(s) on left side */
void _delLesserNodes(struct Node* head)
{
struct Node* current = head;

/* Initialize max */
struct Node* maxnode = head;
struct Node* temp;

while (current != NULL &&


current->next != NULL)
{
/* If current is smaller than max,
then delete current */
if (current->next->data < maxnode->data)
{
temp = current->next;
current->next = temp->next;
free(temp);
}
/* If current is greater than max,
then update max and move current */
else
{
current = current->next;
maxnode = current;
}
}
}

32.Segregate even and odd nodes in a Linked List

PROBLEM : Given a Linked List of integers, write a function to modify the linked list such that
all even numbers appear before all the odd numbers in the modified linked list. Also, keep the
order of even and odd numbers same.

The idea is to get pointer to the last node of list. And then traverse the list starting from the head node
and move the odd valued nodes from their current position to end of the list.

Algorithm:
…1) Get a pointer to the last node.
…2) Move all the odd nodes to the end.
……..a) Consider all odd nodes before the first even node and move them to end.
……..b) Change the head pointer to point to the first even node.
……..b) Consider all odd nodes after the first even node and move them to the end.

void segregateEvenOdd(Node **head_ref)


{
Node *end = *head_ref;
Node *prev = NULL;
Node *curr = *head_ref;

/* Get pointer to the last node */


while (end->next != NULL)
end = end->next;

Node *new_end = end;

/* Consider all odd nodes before the first


even node and move then after end */
while (curr->data % 2 != 0 && curr != end)
{
new_end->next = curr;
curr = curr->next;
new_end->next->next = NULL;
new_end = new_end->next;
}

// 10->8->17->17->15
/* Do following steps only if
there is any even node */
if (curr->data%2 == 0)
{
/* Change the head pointer to
point to first even node */
*head_ref = curr;

/* now current points to


the first even node */
while (curr != end)
{
if ( (curr->data) % 2 == 0 )
{
prev = curr;
curr = curr->next;
}
else
{
/* break the link between
prev and current */
prev->next = curr->next;

/* Make next of curr as NULL */


curr->next = NULL;

/* Move curr to end */


new_end->next = curr;

/* make curr as new end of list */


new_end = curr;

/* Update current pointer to


next of the moved node */
curr = prev->next;
}
}
}

/* We must have prev set before executing


lines following this statement */
else prev = curr;

/* If there are more than 1 odd nodes


and end of original list is odd then
move this node to end to maintain
same order of odd numbers in modified list */

if (new_end != end && (end->data) % 2 != 0)


{
prev->next = end->next;
end->next = NULL;
new_end->next = end;
}
return;
}

Time complexity: O(n)

METHOD 2 :

The idea is to split the linked list into two: one containing all even nodes and other containing all odd
nodes. And finally, attach the odd node linked list after the even node linked list.
To split the Linked List, traverse the original Linked List and move all odd nodes to a separate Linked
List of all odd nodes. At the end of the loop, the original list will have all the even nodes and the odd
node list will have all the odd nodes. To keep the ordering of all nodes the same, we must insert all the
odd nodes at the end of the odd node list. And to do that in constant time, we must keep track of the last
pointer in the odd node list.

// Function to segregate even and odd nodes


void segregateEvenOdd(struct Node **head_ref)
{
// Starting node of list having
// even values.
Node *evenStart = NULL;

// Ending node of even values list.


Node *evenEnd = NULL;

// Starting node of odd values list.


Node *oddStart = NULL;

// Ending node of odd values list.


Node *oddEnd = NULL;

// Node to traverse the list.


Node *currNode = *head_ref;

while(currNode != NULL)
{
int val = currNode -> data;

// If current value is even, add


// it to even values list.
if(val % 2 == 0) {
if(evenStart == NULL)
{
evenStart = currNode;
evenEnd = evenStart ;
}
else{
evenEnd -> next = currNode;
evenEnd = evenEnd -> next;
}
}

// If current value is odd, add


// it to odd values list.
else{
if(oddStart == NULL){
oddStart = currNode;
oddEnd = oddStart;
}
else{
oddEnd -> next = currNode;
oddEnd = oddEnd -> next;
}
}

// Move head pointer one step in


// forward direction
currNode = currNode -> next;
}

// If either odd list or even list is empty,


// no change is required as all elements
// are either even or odd.
if(oddStart == NULL || evenStart == NULL){
return;
}

// Add odd list after even list.


evenEnd -> next = oddStart;
oddEnd -> next = NULL;

// Modify head pointer to


// starting of even list.
*head_ref = evenStart;
}
Time complexity: O(n)

33.Program for n’th node from the end of a Linked List

Method 1 (Use length of linked list)

1) Calculate the length of Linked List. Let the length be len.


2) Print the (len – n + 1)th node from the beginning of the Linked List.
Double pointer concept : First pointer is used to store the address of the variable and second pointer
used to store the address of the first pointer. If we wish to change the value of a variable by a function,
we pass pointer to it. And if we wish to change value of a pointer (i. e., it should start pointing to
something else), we pass pointer to a pointer.

Function to get the nth node from the last of a linked list*/

void printNthFromLast(struct Node* head, int n)


{
int len = 0, i;
struct Node* temp = head;

// count the number of nodes in Linked List


while (temp != NULL) {
temp = temp->next;
len++;
}

// check if value of n is not


// more than length of the linked list
if (len < n)
return;

temp = head;

// get the (len-n+1)th node from the beginning


for (i = 1; i < len - n + 1; i++)
temp = temp->next;
cout << temp->data;

return;

Method 2 (Use two pointers)


Maintain two pointers – reference pointer and main pointer. Initialize both reference and main pointers to
head. First, move the reference pointer to n nodes from head. Now move both pointers one by one until
the reference pointer reaches the end. Now the main pointer will point to nth node from the end. Return
the main pointer

* Function to get the nth node


from the last of a linked list*/
void printNthFromLast(struct Node *head, int n)
{
struct Node *main_ptr = head;
struct Node *ref_ptr = head;

int count = 0;
if(head != NULL)
{
while( count < n )
{
if(ref_ptr == NULL)
{
printf("%d is greater than the no. of "
"nodes in list", n);
return;
}
ref_ptr = ref_ptr->next;
count++;
} /* End of while*/

if(ref_ptr == NULL)
{
head = head->next;
if(head != NULL)
printf("Node no. %d from last is %d ", n, main_ptr->data);
}
else
{
while(ref_ptr != NULL)
{
main_ptr = main_ptr->next;
ref_ptr = ref_ptr->next;
}
printf("Node no. %d from last is %d ", n, main_ptr->data);
}
}
}
Time Complexity: O(n) where n is the length of linked list.

34.Find the first non-repeating character from a stream of characters


PROBLEM : Given a stream of characters, find the first non-repeating character from stream. You
need to tell the first non-repeating character in O(1) time at any moment.

The idea is to use a DLL (Doubly Linked List) to efficiently get the first non-repeating character from a
stream. The DLL contains all non-repeating characters in order, i.eThe head of the DLL contains the first
non-repeating character, the second node contains the second non-repeating and so on.

We also maintain two arrays: one array is to maintain characters that are already visited two
or more times, we call it repeated[],

The other array is an array of pointers to linked list nodes, we call it inDLL[]. The size of both
arrays is equal to alphabet size which is typically 256.

1. Create an empty DLL. Also create two arrays inDLL[] and repeated[] of size 256.
inDLL is an array of pointers to DLL nodes. repeated[] is a boolean array, repeated[x]
is true if x is repeated two or more times, otherwise false. inDLL[x] contains a pointer
to a DLL node if character x is present in DLL, otherwise NULL.

2. Initialize all entries of inDLL[] as NULL and repeated[] as false.


3. To get the first non-repeating character, return character at head of DLL.
4. Following are steps to process a new character ‘x’ in a stream.
○ If repeated[x] is true, ignore this character (x is already repeated two or more
times in the stream)
○ If repeated[x] is false and inDLL[x] is NULL (x is seen for the first time).
Append x to DLL and store address of new DLL node in inDLL[x].
○ If repeated[x] is false and inDLL[x] is not NULL (x is seen a second time). Get
the DLL node of x using inDLL[x] and remove the node. Also, mark inDLL[x]
as NULL and repeated[x] as true.

Note that appending a new node to DLL is O(1) operation if we maintain tail pointer.
Removing a node from DLL is also O(1). So both operations, addition of new character and
finding first non-repeating character take O(1) time.

Below image is a dry run of the above approach:


/ A utility function to append a character x at the end
// of DLL. Note that the function may change head and tail
// pointers, that is why pointers to these pointers are
// passed.

void appendNode( struct node** head_ref ,struct node** tail_ref, char x)


{
struct node* temp = new node;

temp->a = x;

temp->prev = temp->next = NULL;

if (*head_ref == NULL)
{
*head_ref = *tail_ref = temp;
return;
}
(*tail_ref)->next = temp;
temp->prev = *tail_ref;
*tail_ref = temp;
}

// A utility function to remove a node 'temp' fromt DLL.


// Note that the function may change head and tail pointers,
// that is why pointers to these pointers are passed.

void removeNode(struct node** head_ref, struct node** tail_ref, struct node* temp)
{
if (*head_ref == NULL)
return;

if (*head_ref == temp)
*head_ref = (*head_ref)->next;
if (*tail_ref == temp)
*tail_ref = (*tail_ref)->prev;

if (temp->next != NULL)
temp->next->prev = temp->prev;

if (temp->prev != NULL)
temp->prev->next = temp->next;

delete (temp);
}

void findFirstNonRepeating()
{
// inDLL[x] contains pointer to
// a DLL node if x is present
// in DLL. If x is not present, then inDLL[x] is NULL

struct node* inDLL[MAX_CHAR];

// repeated[x] is true if x is repeated two or more


// times. If x is not seen so far or x is seen only
// once. then repeated[x] is false

bool repeated[MAX_CHAR];

// Initialize the above two arrays

struct node *head = NULL, *tail = NULL;

for (int i = 0; i < MAX_CHAR; i++) {


inDLL[i] = NULL;
repeated[i] = false;
}

// Let us consider following stream and see the process


char stream[] = "geeksforgeeksandgeeksquizfor";

for (int i = 0; stream[i]; i++)


{
char x = stream[i];
cout << "Reading " << x << " from stream \n";

// We process this character only if it has not


// occurred or occurred only once. repeated[x] is
// true if x is repeated twice or more.s
if (!repeated[x])
{
// If the character is not in DLL, then add this
// at the end of DLL.
if (inDLL[x] == NULL)
{
appendNode(&head, &tail, stream[i]);
inDLL[x] = tail;
}
else // Otherwise remove this character from DLL
{
removeNode(&head, &tail, inDLL[x]);
inDLL[x] = NULL;
repeated[x]
= true; // Also mark it as repeated
}
}

// Print the current first non-repeating character


// from stream
if (head != NULL)
cout << "First non-repeating character so far "
"is "
<< head->a << endl;
}
}

You might also like