0% found this document useful (0 votes)
8 views

Lab Manual ADSA (Array & Linked List)

Uploaded by

subhash.chandra
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views

Lab Manual ADSA (Array & Linked List)

Uploaded by

subhash.chandra
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 37

Lab Manual

ADSA

1. Maximum and minimum of an array using


minimum number of comparisons

Given an array of size N. The task is to find the maximum and the minimum
element of the array using the minimum number of comparisons.
Examples:
Input: arr[] = {3, 5, 4, 1, 9}
Output: Minimum element is: 1
Maximum element is: 9
Input: arr[] = {22, 14, 8, 17, 35, 3}
Output: Minimum element is: 3
Maximum element is: 35
Step 1: Write functions to find the minimum (setmini) and maximum
(setmaxi) values in the array.
Step 2: In the setmini function:
 Initialize a variable (mini) to INT_MAX.
 Iterate through the array, and if an element is smaller than the current
mini, update mini to that element.
 Return the final value of mini.
Step 3: In the setmaxi function:
 Initialize a variable (maxi) to INT_MIN.
 Iterate through the array, and if an element is larger than the current maxi,
update maxi to that element.
 Return the final value of maxi.
Step 4: In the main function:
 Declare an array and its size.
 Print the result ,Call the setminimum and setmaxi functions to find the
minimum and maximum values.
Below is the implementation of the above approach:
#include <iostream>
#include <limits.h>
using namespace std;

int setmini(int A[], int N)


{
int mini = INT_MAX;
for (int i = 0; i < N; i++) {
if (A[i] < mini) {
mini = A[i];
}
}
return mini;
}
int setmaxi(int A[], int N)
{
int maxi = INT_MIN;

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


if (A[i] > maxi) {
maxi = A[i];
}
}
return maxi;
}
int main()
{
int A[] = { 4, 9, 6, 5, 2, 3 };
int N = 6;
cout <<"Minimum element is: " <<setmini(A, N) << endl;
cout <<"Miximum element is: "<< setmaxi(A, N) << endl;
}
2. Reverse an Array: Write a function to reverse an array in place

Reversing an array means changing the position of each number in the array
to its corresponding position from the end. For example, if a number is at
position 1, its new position will be at Array.length, and similarly, if a number
is at position 2, its new position will be at Array.length – 1, and so on.

Array Reverse in C/C++/Java/Python/JavaScript

To deepen your understanding of array manipulation and other critical


concepts in data structures and algorithms , consider learning from
the Complete Data Structures and Algorithms (DSA) Course . This
comprehensive course covers a wide range of topics, including array
manipulation, linked lists, stacks, queues, trees, graphs, and advanced
algorithms.
Given an array (or string), the task is to reverse the array/string.

Examples:
Input: original_array[] = {1, 2, 3}
Output: array_reversed[] = {3, 2, 1}

Input: original_array[] = {4, 5, 1, 2}


Output: array_reversed[] = {2, 1, 5, 4}
Array Reverse Using a Loop (In-place):
 Iterate through the array using two pointers (start and end).
 Swap elements at the start and end pointers.
 Move the start pointer towards the end and the end pointer towards the
start until they meet or cross each other.
// Iterative C++ program to reverse an array
#include <bits/stdc++.h>;
using namespace std;

/* Function to reverse arr[] from start to end*/


void reverseArray(int arr[], int start, int end)
{
while (start < end) {
int temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
start++;
end--;
}
}

/* Utility function to print an array */


void printArray(int arr[], int size)
{
for (int i = 0; i < size; i++)
cout << arr[i] << " ";

cout << endl;


}

/* Driver function to test above functions */


int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6 };

int n = sizeof(arr) / sizeof(arr[0]);


// To print original array
printArray(arr, n);

// Function calling
reverseArray(arr, 0, n - 1);

cout << "Reversed array is" << endl;

// To print the Reversed array


printArray(arr, n);

return 0;
}

Output
1 2 3 4 5 6
Reversed array is
6 5 4 3 2 1
 Time Complexity: O(n)
o The loop runs through half of the array, so it’s linear with respect
to the array size.
 Auxiliary Space Complexity: O(1)
o In-place reversal, meaning it doesn’t use additional space.

3. Find the Kth Smallest/Largest Element in an Array: Write a function to


find the Kth smallest or largest element in an array.

Given an array arr[] of N distinct elements and a number K, where K is


smaller than the size of the array. Find the K’th smallest element in the given
array.

Examples:
Input: arr[] = {7, 10, 4, 3, 20, 15}, K = 3
Output: 7
Input: arr[] = {7, 10, 4, 3, 20, 15}, K = 4
Output: 10
// C++ program to find K'th smallest element
#include <bits/stdc++.h>
using namespace std;
// Function to return K'th smallest element in a given array
int kthSmallest(int arr[], int N, int K)
{
// Sort the given array
sort(arr, arr + N);

// Return k'th element in the sorted array


return arr[K - 1];
}

// Driver's code
int main()
{
int arr[] = { 12, 3, 5, 7, 19 };
int N = sizeof(arr) / sizeof(arr[0]), K = 2;

// Function call
cout << "K'th smallest element is "
<< kthSmallest(arr, N, K);
return 0;
}

Output
K'th smallest element is 5
Time Complexity: O(N log N)
Auxiliary Space: O(1)

4. Sort an Array of 0s, 1s, and 2s: Given an array containing only 0s, 1s, and
2s, sort the array in linear time.

Sort an array of 0s, 1s and 2s | Dutch National


Flag problem
Last Updated : 10 Jul, 2024


Given an array A[] consisting of only 0s, 1s, and 2s. The task is to sort the array, i.e.,
put all 0s first, then all 1s and all 2s in last.
This problem is the same as the famous “Dutch National Flag problem”. The
problem was proposed by Edsger Dijkstra. The problem is as follows:
Given N balls of colour red, white or blue arranged in a line in random order. You
have to arrange all the balls such that the balls with the same colours are adjacent
with the order of the balls, with the order of the colours being red, white and blue
(i.e., all red coloured balls come first then the white coloured balls and then the blue
coloured balls).
Examples:
Input: {0, 1, 2, 0, 1, 2}
Output: {0, 0, 1, 1, 2, 2}
Explanation: {0, 0, 1, 1, 2, 2} has all 0s first, then all 1s and all 2s in last.
Input: {0, 1, 1, 0, 1, 2, 1, 2, 0, 0, 0, 1}
Output: {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2}
Explanation: {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2} has all 0s first, then all 1s and all 2s in
last.
[Naive Approach] Sorting – O(N * log(N)) Time and O(1) Space:
The naive solution is to simply sort the array using a standard sorting
algorithm or sort library function. This will simply place all the 0s first, then all
1s and 2s at last. This approach requires O(N * log(N)) time and O(1) space.

[Better Approach] Counting 0s, 1s and 2s – Two Pass – O(N) Time


and O(1) Space:
A better solution is to traverse the array once and count number of 0s, 1s
and 2s. Let these counts be c0, c1 and c2. Now traverse the array again, put
c0 (count of 0s) 0s first, then c1 1s and finally c2 2s. This solution works in
O(n) time, but this solution is not stable and requires two traversals of the
array. This approach requires to traverse the array twice, therefore O(N) time
and O(1) space.

// C++ Program to sort an array of 0s, 1s and 2s

#include <iostream>
using namespace std;

// Function to sort the array of 0s, 1s and 2s


void sort012(int a[], int n)
{
int c0 = 0, c1 = 0, c2 = 0;

// Count 0s, 1s and 2s


for (int i = 0; i < n; i++) {
if (a[i] == 0) {
c0 += 1;
}
else if (a[i] == 1) {
c1 += 1;
}
else {
c2 += 1;
}
}

int idx = 0;
// Place all the 0s
for (int i = 0; i < c0; i++)
a[idx++] = 0;

// Place all the 1s


for (int i = 0; i < c1; i++)
a[idx++] = 1;

// Place all the 2s


for (int i = 0; i < c2; i++)
a[idx++] = 2;
}

int main()
{

// Sample Input
int a[] = { 0, 1, 1, 0, 1, 2, 1, 2, 0, 0, 0, 1 };
int n = sizeof(a) / sizeof(a[0]);

sort012(a, n);

for (int i = 0; i < n; i++)


cout << a[i] << " ";
return 0;
}

Output
0 0 0 0 0 1 1 1 1 1 2 2
Time Complexity: O(2 * N), where N is the number of elements in the array
Auxiliary Space: O(1)
The issues with this approach are:
1) It would not work if 0s and 1s represent keys of objects. For example 0s
represents students failed the exam and 1s represent the students passed.
2) Not stable
3) Requires two traversals

[Expected Approach] Dutch National Flag Algorithm – One Pass –


O(N) Time and O(1) Space:
The problem is similar to “Segregate 0s and 1s in an array”. The idea is to
sort the array of size N using three pointers: lo = 0, mid = 0 and hi = N – 1
such that the array is divided into three parts:
 arr[0] to arr[lo – 1]: This part will have all the zeros.
 arr[lo] to arr[mid – 1]: This part will have all the ones.
 arr[hi + 1] to arr[N – 1]: This part will have all the twos.
Traverse over the array till mid <= hi, according to the value of arr[mid] we
can have three cases:
 arr[mid] = 0, then swap arr[lo] and arr[mid] and increment lo by 1
because all the zeros are till index lo – 1 and move to the next element so
increment mid by 1.
 arr[mid] = 1, then move to the next element so increment mid by 1.
 arr[mid] = 2, then swap arr[mid] and arr[hi] and decrement hi by 1
because all the twos are from index hi + 1 to N – 1. Now, we don’t move
to the next element because the element which is now at index mid can
be a 0 and therefore needs to be checked again.
// C++ program to sort an array of 0s, 1s and 2s in a single pass
#include <bits/stdc++.h>
using namespace std;

// Function to sort the input array,


// the array is assumed
// to have values in {0, 1, 2}
void sort012(int a[], int n)
{
int lo = 0;
int hi = n - 1;
int mid = 0;

// Iterate till all the elements


// are sorted
while (mid <= hi) {
switch (a[mid]) {

// If the element is 0
case 0:
swap(a[lo++], a[mid++]);
break;
// If the element is 1 .
case 1:
mid++;
break;

// If the element is 2
case 2:
swap(a[mid], a[hi--]);
break;
}
}
}

// Function to print array arr[]


void printArray(int arr[], int n)
{
// Iterate and print every element
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
}

// Driver Code
int main()
{
// Sample Input
int arr[] = { 0, 1, 1, 0, 1, 2, 1, 2, 0, 0, 0, 1 };
int n = sizeof(arr) / sizeof(arr[0]);

sort012(arr, n);

printArray(arr, n);

return 0;
}

Output
0 0 0 0 0 1 1 1 1 1 2 2

Complexity Analysis of Dutch National Flag Algorithm:


 Time Complexity: O(n), Only one traversal of the array is needed.
 Auxiliary Space : O(1), No extra space is required.
5. Move All Zeroes to End of Array: Write a function to move all zeroes in an
array to the end while maintaining the relative order of other elements

Given an array of random numbers, Push all the zero’s of a given array to
the end of the array. For example, if the given arrays is {1, 9, 8, 4, 0, 0, 2, 7,
0, 6, 0}, it should be changed to {1, 9, 8, 4, 2, 7, 6, 0, 0, 0, 0}. The order of all
other elements should be same. Expected time complexity is O(n) and extra
space is O(1).
Example:
Input : arr[] = {1, 2, 0, 4, 3, 0, 5, 0};
Output : arr[] = {1, 2, 4, 3, 5, 0, 0, 0};
Explanation : There are three 0s that are moved to end

Input : arr[] = {1, 2, 0, 0, 0, 3, 6};


Output : arr[] = {1, 2, 3, 6, 0, 0, 0};
Input: arr[] = {10, 20, 30}
Output : arr[] = {10, 20, 30}
Explanation : No change in array as there are NO 0s

Input: arr[] = {0 , 0}
Output : arr[] = {0, 0}
Explanation : No change in array as there are ALL 0s
#include <bits/stdc++.h>
using namespace std;

vector<int> moveZeros(vector<int>& arr) {


int n = arr.size();
vector<int> res(n); // Result vector

// j: index for non-zeros


// count: Count of zeros
int j = 0, count = 0;

// Move non-zeros to the result


for (int i = 0; i < n; i++) {
if (arr[i] != 0) {
res[j] = arr[i];
j++;
} else {
count++;
}
}
// Fill remaining positions with zeros
for (int i = 0; i < count; i++) {
res[j] = 0;
j++;
}

return res;
}

int main() {
vector<int> arr = {5, 6, 0, 4, 6, 0, 9, 0, 8};
arr = moveZeros(arr);

// Print the modified array


for (int num : arr) {
cout << num << " ";
}
return 0;
}

Output
5 6 4 6 9 8 0 0 0
Time complexity: O(n), where n is the size of elements of the input array.
Auxiliary Space : O(n)

Better (O(n) Time and O(1) Space):


Traverse the given array ‘arr’ from left to right. While traversing, maintain count of
non-zero elements in array. Let the count be ‘count’. For every non-zero element
arr[i], put the element at ‘arr[count]’ and increment ‘count’. After complete traversal,
all non-zero elements have already been shifted to front end and ‘count’ is set as index
of first 0. Now all we need to do is run a loop that makes all elements zero from
‘count’ till end of the array.

Below is the implementation of the above approach.


#include <bits/stdc++.h>
using namespace std;

// Function which pushes all zeros to end of a vector.


void pushZerosToEnd(vector<int>& arr) {
int count = 0; // Count of non-zero elements

// Traverse the vector. If the element is non-zero,


// replace the element at index 'count' with this element
for (int i = 0; i < arr.size(); i++) {
if (arr[i] != 0) {
arr[count++] = arr[i]; // Increment count
}
}

// Now all non-zero elements have been shifted to


// the front. Make all elements 0 from count to end.
while (count < arr.size()) {
arr[count++] = 0;
}
}

// Driver program to test above function


int main() {
vector<int> arr = {1, 9, 8, 4, 0, 0, 2, 7, 0, 6, 0, 9};
pushZerosToEnd(arr);
for (int num : arr) {
cout << num << " ";
}
return 0;
}

Output
1 9 8 4 2 7 6 9 0 0 0 0
The above solution has following issues:
1) Requires two traversals
2) Not Stable : Assume that 0s represent keys of some items, say marks. The above
solution changes order of zeros.

Optimized Solution (One Traversal)


We traverse through the array and count non-zero elements and ignore zeros. For
every non-zero element, we swap it with the element after the last seen non-zero. We
get the index of this element using the count of non-zeros. This approach is mainly
based on Hoare’s partition with 0 considered as pivot.

Below is the implementation of the above approach.


#include <bits/stdc++.h>
using namespace std;

// Function which pushes all zeros to end of a vector.


void moveZeros(vector<int>& arr) {
int count = 0; // Count of non-zero elements

for (int i = 0; i < arr.size(); i++) {


// We ignore 0s and for every non-zero
// element, we swap it with the element
// after the last non-zero element seen
if (arr[i] != 0) {
swap(arr[i], arr[count]);
count++;
}
}
}

// Driver program to test above function


int main() {
vector<int> arr = {1, 9, 8, 4, 0, 0, 2, 7, 0, 6, 0, 9};
moveZeros(arr);
for (int num : arr) {
cout << num << " ";
}
return 0;
}

Output
1 9 8 4 2 7 6 9 0 0 0 0
Time Complexity: O(N), where N is the size of elements of the input array.
Auxiliary Space: O(1)

Using Library Methods:


In C++, there exists a method stable_parition() that we can directly use here to
implement the above method.
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

void moveZeros(std::vector<int> &arr)


{
stable_partition(arr.begin(), arr.end(), [](int n) {
return n != 0; });
}

int main()
{
vector<int> arr{1, 9, 8, 4, 0, 0, 2, 7, 0, 6, 0, 9};
moveZeros(arr);
for (const auto &i : arr)
cout << i << ' ';
return 0;
}

Output
1 9 8 4 2 7 6 9 0 0 0 0

6.Reverse a Linked List



Given a linked list, the task is to reverse the linked list by changing the links between
nodes.
Examples:
Input: Linked List = 1 -> 2 -> 3 -> 4 -> NULL
Output: Reversed Linked List = 4 -> 3 -> 2 -> 1 -> NULL
Input: Linked List = 1 -> 2 -> 3 -> 4 -> 5 -> NULL
Output: Reversed Linked List = 5 -> 4 -> 3 -> 2 -> 1 -> NULL
Input: Linked List = NULL
Output: Reversed Linked List = NULL
Input: Linked List = 1->NULL
Output: Reversed Linked List = 1->NULL
Reverse a Linked List using Iterative Method – O(N) Time and O(1) Space:
The idea is to reverse the links of all nodes using three pointers:
 prev: pointer to keep track of the previous node
 curr: pointer to keep track of the current node
 next: pointer to keep track of the next node
Starting from the first node, initialize curr with the head of linked list
and next with the next node of curr. Update the next pointer
of curr with prev. Finally, move the three pointer by
updating prev with curr and curr with next.
https://media.geeksforgeeks.org/wp-content/cdn-uploads/RGIF2.gif
Follow the steps below to solve the problem:

 Initialize three pointers prev as NULL, curr as head, and next as NULL.
 Iterate through the linked list. In a loop, do the following:
o Before changing the next of curr, store the next node
 next = curr -> next
o Now update the next pointer of curr to the prev
 curr -> next = prev
o Update prev as curr and curr as next
 prev = curr
 curr = next
// Iterative C++ program to reverse a linked list
#include <bits/stdc++.h>
using namespace std;

/* Link list node */


struct Node {
int data;
struct Node* next;
Node(int data)
{
this->data = data;
next = NULL;
}
};

struct LinkedList {
Node* head;
LinkedList() { head = NULL; }

/* Function to reverse the linked list */


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;
}

/* Function to print linked list */


void print()
{
struct Node* temp = head;
while (temp != NULL) {
cout << temp->data << " ";
temp = temp->next;
}
}

void push(int data)


{
Node* temp = new Node(data);
temp->next = head;
head = temp;
}
};

/* Driver code*/
int main()
{
/* Start with the empty list */
LinkedList ll;
ll.push(20);
ll.push(4);
ll.push(15);
ll.push(85);

cout << "Given linked list\n";


ll.print();

ll.reverse();

cout << "\nReversed linked list \n";


ll.print();
return 0;
}

Output

Given linked list


85 15 4 20
Reversed linked list
20 4 15 85
Time Complexity: O(N), Traversing over the linked list of size N.
Auxiliary Space: O(1)

7. Detect a Cycle in a Linked List: Write a function to detect if a


cycle exists in a linked list.
Detect loop in a linked list using Floyd’s Cycle-Finding Algorithm:
This algorithm is used to find a loop in a linked list. It uses two pointers one
moving twice as fast as the other one. The faster one is called the faster
pointer and the other one is called the slow pointer.
Follow the steps below to solve the problem:
 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 the linked list doesn’t have a loop.

//User function template for C++

/*

struct Node
{
int data;
struct Node *next;
Node(int x) {
data = x;
next = NULL;
}

*/
class Solution
{
public:
//Function to check if the linked list has a loop.
bool detectLoop(Node* head)
{
// your code here
Node* slow = head;
Node* fast = head;

// Step 1: Traverse the list to detect a loop


while (fast != nullptr && fast->next != nullptr) {
// Move slow one step
slow = slow->next;
// Move fast two steps
fast = fast->next->next;

// Step 2: If the slow and fast pointers


// meet, there is a loop
if (slow == fast) {
// return the number of nodes
// in the loop
return true;
}
}

// Step 3: If the fast pointer


// reaches the end, there is no loop
return false;

}
};

8.Find Middle of the Linked List



Given a Singly Linked List, the task is to find the middle of the linked list. If the
number of nodes are even, then there would be two middle nodes, so return the second
middle node.
Example:
Input: linked list = 1 -> 2 -> 3 -> 4 -> 5
Output: 3
Explanation: There are 5 nodes in the linked list and there is one middle node whose
value is 3.
Input: linked list = 1 -> 2 -> 3 -> 4 -> 5 -> 6
Output: 4
Explanation: There are 6 nodes in the linked list, so we have two middle nodes: 3 and
4, but we will return the second middle node which is 4.
Find middle of the Linked List using Extra Memory (Brute Force):
Store the entire linked list in a vector or Array List such that each index contains the
value of a node. Now, to find the middle of the linked list, we can simply return the
value present at the middle of the vector or Array List.
Step-by-step algorithm:
 Declare a vector(or Array list), say v to store values of all nodes of the linked list.
 Iterate over the linked list and for each node, push the value of the node in v.
 After iterating over the entire linked list, find the middle index of the vector,
say mid_index= v.size()/2.
 Return v[middleIdx] as the middle element of the linked list.
// C++ program to illustrate how to find the middle element
// by storing element in a vector
#include <iostream>
#include <vector>

using namespace std;

// A singly linked list node


class Node {
public:
int data;
Node* next;

// Constructor to initialize a new node with data


Node(int new_data) {
this->data = new_data;
this->next = nullptr;
}
};

// Function to find the middle element of the linked list


int getMiddle(Node* head) {

// Vector to store the values of all nodes in the order


vector<int> list_values;

// Traverse through the entire linked list and push all


// the values into the vector
while (head != nullptr) {
list_values.push_back(head->data);
head = head->next;
}

// Find the middle index by dividing the size by 2


int mid_index = list_values.size() / 2;
// Return the value stored at the middle index
return list_values[mid_index];
}

int main() {

// Create a hard-coded linked list:


// 10 -> 20 -> 30 -> 40 -> 50 -> 60 -> 70
Node* head = new Node(10);
head->next = new Node(20);
head->next->next = new Node(30);
head->next->next->next = new Node(40);
head->next->next->next->next = new Node(50);
head->next->next->next->next->next = new Node(60);
head->next->next->next->next->next->next = new Node(70);

// Example of printing the middle value of the


// linked list
cout << "Middle Value Of Linked List is: "
<< getMiddle(head) << endl;

return 0;
}
Output
Middle Value Of Linked List is: 40
Time Complexity: O(N), where N is the number of nodes in the linked list.
Auxiliary Space: O(N)

Find Middle of the Linked List using Floyd’s Cycle Finding Algorithm:
We can use the Floyd’s Cycle Finding Algorithm, also known as Hare and
Tortoise Algorithm to find the middle of the linked list. Traverse linked list
using a slow pointer and a fast pointer. Move the slow pointer to the next
node(one node forward) and the fast pointer to the next of the next node(two
nodes forward). When the fast pointer reaches the last node or NULL, then
the slow pointer will reach the middle of the linked list.
In case of odd number of nodes in the linked list, slow_ptr will reach the
middle node when fast_ptr will reach the last node and in case
of even number of nodes in the linked list, slow_ptr will reach the middle
node when fast_ptr will become NULL.
Step-by-step algorithm:
 Initialize a slow pointer slow_ptr = head and a fast pointer fast_ptr =
head.
 Iterate till fast_ptr reaches the last node(fast_ptr->next != NULL) or
becomes NULL(fast_ptr != NULL).
 Move fast_ptr by two nodes, fast_ptr = fast_ptr->next->next.
 Move slow_ptr by one node, slow_ptr = slow_ptr->next.
 As soon as the fast_ptr reaches the last node or becomes NULL, return
the value at slow_ptr.
Below image shows how getMiddle() function works in the code:

1/3

Below is the implementation of the above algorithm:


C++CJavaPythonC#JavaScript

// C++ program to illustrate how to find the middle element


// by using Floyd's Cycle Finding Algorithm
#include <iostream>
using namespace std;

// A singly linked list node


class Node {
public:
int data;
Node* next;

// Constructor to initialize a new node with data


Node(int new_data) {
this->data = new_data;
this->next = nullptr;
}
};

// Function to get the middle of the linked list


int getMiddle(Node* head) {

// Initialize the slow and fast pointer to the head of


// the linked list
Node* slow_ptr = head;
Node* fast_ptr = head;

while (fast_ptr != NULL && fast_ptr->next != NULL) {

// Move the fast pointer by two nodes


fast_ptr = fast_ptr->next->next;

// Move the slow pointer by one node


slow_ptr = slow_ptr->next;
}

// Return the slow pointer which is currenlty pointing


// to the middle node of the linked list
return slow_ptr->data;
}

// Driver Code
int main() {

// Create a hard-coded linked list:


// 10 -> 20 -> 30 -> 40 -> 50 -> 60 -> 70
Node* head = new Node(10);
head->next = new Node(20);
head->next->next = new Node(30);
head->next->next->next = new Node(40);
head->next->next->next->next = new Node(50);
head->next->next->next->next->next = new Node(60);
head->next->next->next->next->next->next = new Node(70);

// Example of printing the middle value of the


// linked list
cout << "Middle Value Of Linked List is: "
<< getMiddle(head) << endl;

return 0;
}

Output
Middle Value Of Linked List is: 40
Time Complexity: O(N), where N is the number of nodes in the linked list.
Auxiliary Space: O(1)
9. Merge two sorted lists (in-place)

Given two sorted lists, merge them so as to produce a combined sorted list
(without using extra space).
Input : a: 5->7->9, b: 4->6->8
Output : 4->5->6->7->8->9
Explanation: The output list is in sorted order.

Input : a: ->3->5->7, b: 2->4


Output : 1->2->3->4->5->7
Explanation: The output list is in sorted order.
We have earlier discussed about different approaches to create a merged
linked list such that the merged list contains a copy of all the nodes. Here we
are going to discuss in-place merge.
Using Recursion:
1. Compare the heads of both linked lists.
2. Find the smaller node among the two head nodes. The current element
will be the smaller node among two head nodes.
3. The rest elements of both lists will appear after that.
4. Now run a recursive function with parameters, the next node of the
smaller element, and the other head.
5. The recursive function will return the next smaller element linked with rest
of the sorted element. Now point the next of current element to that,
i.e curr_ele->next=recursivefunction()
6. Handle some corner cases.

 If both the heads are NULL return null.


 If one head is null return the other.
#include <iostream>
using namespace std;

struct Node {
int data;
Node* next;
Node(int key) {
data = key;
next = nullptr;
}
};

// Function to merge two sorted linked lists


Node* merge(Node* a, Node* b) {
if (!a) return b;
if (!b) return a;

// If a's data is less than or equal


// to b's data
if (a->data <= b->data) {

// If a has more than one element remaining


if (a->next) a->next = merge(a->next, b);

// Attach b to the end of a


else a->next = b;

return a;
} else {

// If b has more than one element remaining


if (b->next) b->next = merge(a, b->next);

// Attach a to the end of b


else b->next = a;

return b;
}
}

// Function to print a linked list


void printList(Node* node) {
while (node != nullptr) {
cout << node->data << " ";
node = node->next;
}
}

// Driver program
int main() {
// 1->3->5 LinkedList created
Node* a = new Node(1);
a->next = new Node(3);
a->next->next = new Node(5);

// 0->2->4 LinkedList created


Node* b = new Node(0);
b->next = new Node(2);
b->next->next = new Node(4);

Node* res = merge(a, b);


printList(res);
return 0;
}

Output
0 1 2 3 4 5
Time complexity: O(m + n), Only one traversal of the linked lists are
needed.
Auxiliary Space: O(n) If the recursive stack space is taken into
consideration.
Iterative Solution
Same approach as recursive solution
1. Traverse the list from start to end.
2. If the head node of second list lies in between two nodes of the first list,
insert it there and make the next node of second list the head. Continue
this until there is no node left in both lists, i.e. both the lists are traversed.
3. If the first list has reached end while traversing, point the next node to the
head of second list.
Note: Compare both the lists where the list with a smaller head value is the
first list.
C++CJavaPythonC#JavaScript

#include <bits/stdc++.h>
using namespace std;

struct Node {
int data;
Node* next;
Node(int key) {
data = key;
next = nullptr;
}
};

// Merges two lists with headers as a and b.


// It assumes that a's data is smaller than
// or equal to b's data.
Node* mergeUtil(Node* a, Node* b) {

// if only one node in the first list


// simply point its head to the second list
if (!a->next) {
a->next = b;
return a;
}

// Initialize current and next pointers of


// both lists
Node *curr1 = a, *next1 = a->next;
Node *curr2 = b, *next2 = b->next;

while (next1 && curr2) {

// if curr2 lies in between curr1 and next1


// then do curr1->curr2->next1
if (curr2->data >= curr1->data && curr2->data <= next1->data) {
next2 = curr2->next;
curr1->next = curr2;
curr2->next = next1;

// now let curr1 and curr2 point


// to their immediate next pointers
curr1 = curr2;
curr2 = next2;
}
else {

// if more nodes in the first list


if (next1->next) {
next1 = next1->next;
curr1 = curr1->next;
}

// else point the last node of the first list


// to the remaining nodes of the second list
else {
next1->next = curr2;
return a;
}
}
}
return a;
}

// Merges two given lists in-place. This function


// mainly compares head nodes and calls mergeUtil()
Node* merge(Node* a, Node* b) {
if (!a)
return b;
if (!b)
return a;
// start with the linked list
// whose head data is the least
if (a->data < b->data)
return mergeUtil(a, b);
else
return mergeUtil(b, a);
}

// A utility function to print a linked list


void printList(Node* node) {
while (node != nullptr) {
cout << node->data << " ";
node = node->next;
}
}

// Driver program
int main() {
// 1->3->5 LinkedList created
Node* a = new Node(1);
a->next = new Node(3);
a->next->next = new Node(5);

// 0->2->4 LinkedList created


Node* b = new Node(0);
b->next = new Node(2);
b->next->next = new Node(4);

Node* res = merge(a, b);

printList(res);
return 0;
}

Output
0 1 2 3 4 5
Time complexity: O(m + n), As only one traversal of the linked lists is
needed.
Auxiliary Space: O(1), As there is no space required.

10. Delete Nth node from the end of the given


linked list

Given a linked list and an integer N, the task is to delete the Nth node from
the end of the given linked list.
Examples:
Input: 2 -> 3 -> 1 -> 7 -> NULL, N = 1
Output:
The created linked list is:
2317
The linked list after deletion is:
231

Input: 1 -> 2 -> 3 -> 4 -> NULL, N = 4


Output:
The created linked list is:
1234
The linked list after deletion is:
234
Intuition:
Lets K be the total nodes in the linked list.
Observation : The Nth node from the end is (K-N+1)th node from the
beginning.
So the problem simplifies down to that we have to find (K-N+1)th node from
the beginning.
 One way of doing it is to find the length (K) of the linked list in one pass
and then in the second pass move (K-N+1) step from the beginning to
reach the Nth node from the end.
 To do it in one pass. Let’s take the first pointer and move N step from the
beginning. Now the first pointer is (K-N+1) steps away from the last
node, which is the same number of steps the second pointer require to
move from the beginning to reach the Nth node from the end.
// C++ code for the deleting a node from end
// in two traversal
#include <bits/stdc++.h>
using namespace std;

struct Node {
int data;
struct Node* next;
Node(int value)
{
this->data = value;
this->next = NULL;
}
};

int length(Node* head)


{
Node* temp = head;
int count = 0;
while (temp != NULL) {
count++;
temp = temp->next;
}
return count;
}

void printList(Node* head)


{
Node* ptr = head;
while (ptr != NULL) {
cout << ptr->data << " ";
ptr = ptr->next;
}
cout << endl;
}

Node* deleteNthNodeFromEnd(Node* head, int n)


{
int Length = length(head);
int nodeFromBeginning = Length - n + 1;
Node* prev = NULL;
Node* temp = head;
for (int i = 1; i < nodeFromBeginning; i++) {
prev = temp;
temp = temp->next;
}
if (prev == NULL) {
head = head->next;
return head;
}
else {
prev->next = prev->next->next;
return head;
}
}

int main()
{
Node* head = new Node(1);
head->next = new Node(2);
head->next->next = new Node(3);
head->next->next->next = new Node(4);
head->next->next->next->next = new Node(5);
cout<<"Linked List before Deletion:"<<endl;
printList(head);

head = deleteNthNodeFromEnd(head, 4);

cout<<"Linked List after Deletion: "<<endl;


printList(head);
return 0;
}

Output
Linked List before Deletion:
1 2 3 4 5
Linked List after Deletion:
1 3 4 5
Two Pointer Approach – Slow and Fast Pointers
This problem can be solved by using two pointer approach as below:
 Take two pointers – fast and slow. And initialize their values as head node
 Iterate fast pointer till the value of n.
 Now, start iteration of fast pointer till the None value of the linked list.
Also, iterate slow pointer.
 Hence, once the fast pointer will reach to the end the slow pointer will
reach the node which you want to delete.
 Replace the next node of the slow pointer with the next to next node of
the slow pointer.
C++JavaPythonC#JavaScript
// C++ code for the deleting a node from end using two
// pointer approach

#include <iostream>
using namespace std;

class LinkedList {
public:
// structure of a node
class Node {
public:
int data;
Node* next;
Node(int d)
{
data = d;
next = NULL;
}
};

// Head node
Node* head;

// Function for inserting a node at the beginning


void push(int data)
{
Node* new_node = new Node(data);
new_node->next = head;
head = new_node;
}
// Function to display the nodes in the list.
void display()
{
Node* temp = head;
while (temp != NULL) {
cout << temp->data << endl;
temp = temp->next;
}
}

// Function to delete the nth node from the end.


Node* deleteNthNodeFromEnd(Node* head, int n)
{
if(head==NULL) {
cout<<"Err : List is empty"<<endl;
return head;
}

if(n<=0) {
cout<<"Err : Number should be positive"<<endl;
return head;
}

Node* fast = head;


Node* slow = head;

for (int i = 1; i <=n; i++) {


if(fast == NULL && i!=n-1) {
cout<<"Err : Number is greater than length of List"<<endl;
return head;
}
fast = fast->next;
}

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

while (fast->next != NULL) {


fast = fast->next;
slow = slow->next;
}
slow->next = slow->next->next;
return head;
}
};

int main()
{

LinkedList* l = new LinkedList();

// Create a list 1->2->3->4->5->NULL


l->push(5);
l->push(4);
l->push(3);
l->push(2);
l->push(1);
cout << "***** Linked List Before deletion *****"
<< endl;
l->display();

cout << "************** Delete nth Node from the End "
"*****"
<< endl;
l->head = l->deleteNthNodeFromEnd(l->head, 1);

cout << "*********** Linked List after Deletion *****"


<< endl;
l->display();

return 0;
}

// This code is contributed by lokesh (lokeshmvs21).

Output
***** Linked List Before deletion *****
1
2
3
4
5
************** Delete nth Node from the End *****
*********** Linked List after Deletion *****
1
2
3
4
Time complexity: O(n)
Auxiliary Space : O(1) using constant space

You might also like