Lab Manual ADSA (Array & Linked List)
Lab Manual ADSA (Array & Linked List)
ADSA
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.
Examples:
Input: original_array[] = {1, 2, 3}
Output: array_reversed[] = {3, 2, 1}
// Function calling
reverseArray(arr, 0, n - 1);
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.
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);
// 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.
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.
#include <iostream>
using namespace std;
int idx = 0;
// Place all the 0s
for (int i = 0; i < c0; i++)
a[idx++] = 0;
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);
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
// 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;
}
}
}
// 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
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[] = {0 , 0}
Output : arr[] = {0, 0}
Explanation : No change in array as there are ALL 0s
#include <bits/stdc++.h>
using namespace std;
return res;
}
int main() {
vector<int> arr = {5, 6, 0, 4, 6, 0, 9, 0, 8};
arr = moveZeros(arr);
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)
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.
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)
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
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;
struct LinkedList {
Node* head;
LinkedList() { head = NULL; }
/* Driver code*/
int main()
{
/* Start with the empty list */
LinkedList ll;
ll.push(20);
ll.push(4);
ll.push(15);
ll.push(85);
ll.reverse();
Output
/*
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;
}
};
int main() {
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
// Driver Code
int main() {
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.
struct Node {
int data;
Node* next;
Node(int key) {
data = key;
next = nullptr;
}
};
return a;
} else {
return b;
}
}
// 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);
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;
}
};
// 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);
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.
struct Node {
int data;
struct Node* next;
Node(int value)
{
this->data = value;
this->next = NULL;
}
};
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);
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;
if(n<=0) {
cout<<"Err : Number should be positive"<<endl;
return head;
}
if (fast == NULL) {
return head->next;
}
int main()
{
cout << "************** Delete nth Node from the End "
"*****"
<< endl;
l->head = l->deleteNthNodeFromEnd(l->head, 1);
return 0;
}
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