ACA Lab
ACA Lab
USN: 1MS21EC098
Section: A Section
1 Arrays
1.1 Linear Search
Algorithm:
1. Start from the first element of the array.
2. Compare the target element with the current element.
3. If the current element matches the target, return the index of the current element.
4. If the end of the array is reached without finding the target, return -1 to indicate that the element is not present.
Time Complexity:
• Best case: O(1) (when the element is found at the first position)
• Worst case: O(n) (when the element is not present or is found at the last position)
• Average case: O(n) (on average, the element might be somewhere in the middle)
Space Complexity:
• The space complexity is O(1) because constant space is used, as no extra space is required apart from the input
array and the target element.
Code:
# include < iostream >
using namespace std ;
int main ()
{
int n , target ;
cout << " Enter the number of elements in the array : " ;
cin >> n ;
int arr [ n ];
cout << " Enter " << n << " elements of the array : " ;
for ( int i = 0; i < n ; i ++)
cin >> arr [ i ];
cout << " Enter the target element to search for : " ;
cin >> target ;
return 0;
}
Output 1:
1
Enter the number of elements in the array: 5
Enter 5 elements of the array: 5 3 9 1 6
Enter the target element to search for: 9
Index of 9: 2
Output 2:
Enter the number of elements in the array: 5
Enter 5 elements of the array: 5 3 9 1 6
Enter the target element to search for: 4
Element not found
int main ()
{
int n , target ;
2
cout << " Enter the number of elements in the array : " ;
cin >> n ;
int arr [ n ];
cout << " Enter " << n << " elements of the array ( sorted in ascending order ) : " ;
for ( int i = 0; i < n ; i ++)
cin >> arr [ i ];
cout << " Enter the target element to search for : " ;
cin >> target ;
if ( result != -1)
cout << " Element found at index " << result << endl ;
else
cout << " Element not found " << endl ;
return 0;
}
Output 1:
Enter the number of elements in the array: 10
Enter 10 elements of the array (sorted in ascending order): 1 3 5 7 9 11 13 15 17 19
Enter the target element to search for: 7
Element found at index 3
Output 2:
Enter the number of elements in the array: 5
Enter 5 elements of the array (sorted in ascending order): 2 4 6 8 10
Enter the target element to search for: 3
Element not found
6. If low exceeds high, the target is not in the array, so return -1.
Time Complexity:
• Best case: O(1) (when the element is found at the first position)
• Worst case: O(n) (when the element is not present or search space is large)
• Average case: O(log log n) (under ideal conditions)
Space Complexity:
• O(1) (constant space used as no extra space is required other than the input array and the target)
Code:
3
# include < iostream >
using namespace std ;
while ( low <= high && target >= arr [ low ] && target <= arr [ high ])
{
int pos = low + (( target - arr [ low ]) * ( high - low ) ) / ( arr [ high ] - arr [ low ]) ;
int main ()
{
int n , target ;
cout << " Enter the number of elements in the array : " ;
cin >> n ;
int arr [ n ];
cout << " Enter " << n << " elements of the array ( sorted in ascending order ) : " ;
for ( int i = 0; i < n ; i ++)
cin >> arr [ i ];
cout << " Enter the target element to search for : " ;
cin >> target ;
if ( result != -1)
cout << " Element found at index " << result << endl ;
else
cout << " Element not found " << endl ;
return 0;
}
Output 1:
Enter the number of elements in the array: 10
Enter 10 elements of the array (sorted in ascending order): 1 3 5 7 9 11 13 15 17 19
Enter the target element to search for: 7
Element found at index 3
Output 2:
Enter the number of elements in the array: 5
Enter 5 elements of the array (sorted in ascending order): 2 4 6 8 10
Enter the target element to search for: 3
Element not found
4
4. Return the updated array.
Time Complexity:
• Best case: O(1) (when the element is inserted at the last position)
• Worst case: O(n) (when the element is inserted at the beginning or middle, causing a shift of all elements)
• Average case: O(n) (shifting elements for insertion)
Space Complexity:
• O(1) (constant space used, no extra space needed apart from the input array)
Code:
# include < iostream >
using namespace std ;
void insertElement ( int arr [] , int &n , int element , int pos )
{
for ( int i = n - 1; i >= pos ; i - -)
arr [ i + 1] = arr [ i ];
int main ()
{
int n , element , pos ;
cout << " Enter the number of elements in the array : " ;
cin >> n ;
cout << " Enter " << n << " elements of the array : " ;
for ( int i = 0; i < n ; i ++)
cin >> arr [ i ];
return 0;
}
Output 1:
Enter the number of elements in the array: 5
Enter 5 elements of the array: 1 2 3 4 5
Enter the element to insert: 6
Enter the position to insert the element (0-based index): 2
Array after insertion: 1 2 6 3 4 5
Output 2:
5
1.5 Deleting an Element from an Array
Algorithm:
1. Take the input array, the element to be deleted, and the position of the element to be deleted.
2. If the position is valid, shift all elements from the position to the left by one place.
3. Decrease the size of the array.
4. Return the updated array.
Time Complexity:
• Best case: O(1) (when the element to be deleted is at the last position)
• Worst case: O(n) (when the element is deleted from the beginning or middle, causing a shift of all elements)
• Average case: O(n) (shifting elements for deletion)
Space Complexity:
• O(1) (constant space used, no extra space needed apart from the input array)
Code:
# include < iostream >
using namespace std ;
int main ()
{
int n , pos ;
cout << " Enter the number of elements in the array : " ;
cin >> n ;
int arr [ n ];
cout << " Enter " << n << " elements of the array : " ;
for ( int i = 0; i < n ; i ++)
cin >> arr [ i ];
cout << " Enter the position to delete the element from (0 - based index ) : " ;
cin >> pos ;
return 0;
}
Output 1:
Enter the number of elements in the array: 5
Enter 5 elements of the array: 1 2 3 4 5
Enter the position to delete the element from (0-based index): 2
Array after deletion: 1 2 4 5
Output 2:
Enter the number of elements in the array: 4
Enter 4 elements of the array: 10 20 30 40
Enter the position to delete the element from (0-based index): 1
Array after deletion: 10 30 40
6
1.6 Sub array with a given sum
Algorithm:
1. Initialize two pointers, start and end, both set to 0. Also, initialize a variable currentSum to store the sum of
elements in the current window.
2. Move the end pointer to expand the window by adding elements to currentSum.
3. If currentSum becomes equal to the target sum, return the indices of the subarray.
4. If currentSum exceeds the target sum, move the start pointer to shrink the window until currentSum becomes
less than or equal to the target sum.
5. If no subarray is found that satisfies the condition, return a message indicating no such subarray exists.
Time Complexity:
• Best case: O(n) (when the subarray is found early)
• Worst case: O(n) (the end pointer moves through the entire array and start only moves to the right as needed)
• Average case: O(n) (linear time complexity)
Space Complexity:
• O(1) (constant space used, only a few variables are required)
Code:
# include < iostream >
using namespace std ;
if ( currentSum == targetSum )
{
cout << " Subarray with the given sum found between indices " << start << " and " << end <<
endl ;
return true ;
}
}
cout << " No subarray with the given sum exists . " << endl ;
return false ;
}
int main ()
{
int n , targetSum ;
cout << " Enter the number of elements in the array : " ;
cin >> n ;
int arr [ n ];
cout << " Enter " << n << " elements of the array : " ;
for ( int i = 0; i < n ; i ++)
cin >> arr [ i ];
7
cin >> targetSum ;
f i n d S u b a r r a y W i t h S u m ( arr , n , targetSum ) ;
return 0;
}
Output 1:
Enter the number of elements in the array: 7
Enter 7 elements of the array: 1 4 20 3 10 5 2
Enter the target sum: 33
Subarray with the given sum found between indices 2 and 4
Output 2:
Enter the number of elements in the array: 5
Enter 5 elements of the array: 1 2 3 7 5
Enter the target sum: 12
Subarray with the given sum found between indices 2 and 3
8
if ( isAscending )
cout << " The array is sorted in ascending order . " << endl ;
else if ( isDescending )
cout << " The array is sorted in descending order . " << endl ;
else
cout << " The array is not sorted . " << endl ;
}
int main ()
{
int n ;
cout << " Enter the number of elements in the array : " ;
cin >> n ;
int arr [ n ];
cout << " Enter " << n << " elements of the array : " ;
for ( int i = 0; i < n ; i ++)
cin >> arr [ i ];
c he ck Ar r ay Or de r ( arr , n ) ;
return 0;
}
Output 1:
Enter the number of elements in the array: 5
Enter 5 elements of the array: 1 2 3 4 5
The array is sorted in ascending order.
Output 2:
Time Complexity:
• Best case: O(n + m) (when elements are evenly distributed and no additional operations are needed)
• Worst case: O(n + m) (we have to traverse all elements in both arrays)
9
# include < iostream >
using namespace std ;
while ( i < n )
merged [ k ++] = arr1 [ i ++];
while ( j < m )
merged [ k ++] = arr2 [ j ++];
int main ()
{
int n , m ;
cout << " Enter the number of elements in the first array : " ;
cin >> n ;
int arr1 [ n ];
cout << " Enter the elements of the first array : " ;
for ( int i = 0; i < n ; i ++)
cin >> arr1 [ i ];
cout << " Enter the number of elements in the second array : " ;
cin >> m ;
int arr2 [ m ];
cout << " Enter the elements of the second array : " ;
for ( int i = 0; i < m ; i ++)
cin >> arr2 [ i ];
return 0;
}
Output 1:
Output 2:
Enter the number of elements in the first array: 2
Enter the elements of the first array: 3 10
Enter the number of elements in the second array: 3
Enter the elements of the second array: 1 5 8
Merged array: 1 3 5 8 10
10
1. Initialize two pointers: left at the start of the array and right at the end of the array.
2. Swap the elements at the left and right pointers.
3. Increment the left pointer and decrement the right pointer.
4. Continue swapping elements until the left pointer is no longer less than the right pointer.
5. Return the reversed array.
Time Complexity:
• Best case: O(n) (the array is reversed in a single pass)
• Worst case: O(n) (the array is reversed in a single pass)
• Average case: O(n) (linear time complexity)
Space Complexity:
• O(1) (constant space used, only two pointers are required)
Code:
# include < iostream >
using namespace std ;
int main ()
{
int n ;
cout << " Enter the number of elements in the array : " ;
cin >> n ;
int arr [ n ];
cout << " Enter " << n << " elements of the array : " ;
for ( int i = 0; i < n ; i ++)
cin >> arr [ i ];
reverseArray ( arr , n ) ;
return 0;
}
Output 1:
Enter the number of elements in the array: 5
Enter 5 elements of the array: 1 2 3 4 5
Reversed array: 5 4 3 2 1
Output 2:
Enter the number of elements in the array: 4
Enter 4 elements of the array: 10 20 30 40
Reversed array: 40 30 20 10
11
1.10 Count Inversions
Algorithm:
1. An inversion is a pair of elements in the array where the first element is greater than the second element and the
first element appears before the second.
2. Use a modified merge sort algorithm to count inversions:
• While merging two halves, count how many elements in the left half are greater than elements in the right half.
• For every element in the left half that is greater than the current element in the right half, there is an inversion.
3. Recursively divide the array into two halves, count inversions in the left and right halves, and then merge them,
while counting inversions during the merge.
Time Complexity:
• Best case: O(n log n) (when the array is already partially sorted)
• Worst case: O(n log n) (divide and merge operations for each element)
• Average case: O(n log n) (merge sort complexity)
Space Complexity:
• O(n) (for the auxiliary space used during merge operations)
Code:
# include < iostream >
using namespace std ;
int mergeAndCount ( int arr [] , int temp [] , int left , int right )
{
int mid , i , j , k ;
int inv_count = 0;
int merge ( int arr [] , int temp [] , int left , int mid , int right )
{
int i = left , j = mid + 1 , k = left , inv_count = 0;
return inv_count ;
}
12
int main ()
{
int n ;
cout << " Enter the number of elements in the array : " ;
cin >> n ;
cout << " Enter " << n << " elements of the array : " ;
for ( int i = 0; i < n ; i ++)
cin >> arr [ i ];
cout << " Number of inversions in the array : " << result << endl ;
return 0;
}
Output 1:
Enter the number of elements in the array: 5
Enter 5 elements of the array: 1 3 2 3 1
Number of inversions in the array: 4
Output 2:
Enter the number of elements in the array: 6
Enter 6 elements of the array: 5 4 3 2 1 0
Number of inversions in the array: 15
13
bool isBalanced ( string expr )
{
stack < char > s ;
unordered_map < char , char > m a t c h i n g P a r e n t h e s e s = {{ ’) ’ , ’( ’} , { ’] ’ , ’[ ’} , { ’} ’ , ’{ ’ }};
int main ()
{
string expr ;
if ( isBalanced ( expr ) )
cout << " The expression is balanced . " << endl ;
else
cout << " The expression is not balanced . " << endl ;
return 0;
}
Output 1:
Enter the expression: {[(a + b) * c] / d}
The expression is balanced.
Output 2:
Enter the expression: {(a + b) * c] / d}
The expression is not balanced.
14
Code:
# include < iostream >
# include < queue >
using namespace std ;
class S t a c k U s i n g Q u e u e s
{
private :
queue < int > queue1 , queue2 ;
public :
void push ( int x )
{
queue1 . push ( x ) ;
}
int pop ()
{
if ( queue1 . empty () )
{
cout << " Stack is empty ! " << endl ;
return -1;
}
return topElement ;
}
int top ()
{
if ( queue1 . empty () )
{
cout << " Stack is empty ! " << endl ;
return -1;
}
bool isEmpty ()
{
return queue1 . empty () ;
}
};
int main ()
{
S t a c k U s i n g Q u e ue s stack ;
int choice , value ;
while ( true )
{
cout << " \ n1 . Push \ n2 . Pop \ n3 . Top \ n4 . Check if Empty \ n5 . Exit \ n " ;
cout << " Enter your choice : " ;
15
cin >> choice ;
switch ( choice )
{
case 1:
cout << " Enter value to push : " ;
cin >> value ;
stack . push ( value ) ;
break ;
case 2:
cout << " Popped value : " << stack . pop () << endl ;
break ;
case 3:
cout << " Top value : " << stack . top () << endl ;
break ;
case 4:
cout << " Is stack empty ? " << ( stack . isEmpty () ? " Yes " : " No " ) << endl ;
break ;
case 5:
return 0;
default :
cout << " Invalid choice ! Please try again . " << endl ;
}
}
return 0;
}
Output 1:
1. Push
2. Pop
3. Top
4. Check if Empty
5. Exit
Enter your choice: 1
Enter value to push: 10
1. Push
2. Pop
3. Top
4. Check if Empty
5. Exit
Enter your choice: 1
Enter value to push: 20
1. Push
2. Pop
3. Top
4. Check if Empty
5. Exit
Enter your choice: 3
Top value: 20
1. Push
2. Pop
3. Top
4. Check if Empty
5. Exit
Enter your choice: 2
Popped value: 20
1. Push
2. Pop
3. Top
16
4. Check if Empty
5. Exit
Enter your choice: 4
Is stack empty? No
Output 2:
1. Push
2. Pop
3. Top
4. Check if Empty
5. Exit
Enter your choice: 1
Enter value to push: 5
1. Push
2. Pop
3. Top
4. Check if Empty
5. Exit
Enter your choice: 1
Enter value to push: 15
1. Push
2. Pop
3. Top
4. Check if Empty
5. Exit
Enter your choice: 2
Popped value: 15
1. Push
2. Pop
3. Top
4. Check if Empty
5. Exit
Enter your choice: 3
Top value: 5
1. Create an empty queue to store characters in the order they appear, and a hash map (or array) to store the frequency
of each character.
2. Traverse the string:
• For each character, increment its frequency in the hash map.
• If the character’s frequency is 1, enqueue it into the queue.
• If the character’s frequency is more than 1, ignore it.
3. After traversing the string, dequeue characters from the front of the queue until you find one with a frequency of 1.
4. Return the first non-repeating character.
5. If no such character exists, return a special value (e.g., -1 or ’ ’) to indicate that all characters are repeating.
Time Complexity:
17
• Best case: O(n) (when the first non-repeating character is found early in the queue)
• Worst case: O(n) (requires traversal of the string and queue operations)
• Average case: O(n) (linear time complexity)
Space Complexity:
• O(k) (where k is the number of unique characters in the string, assuming we use a hash map and a queue)
Code:
# include < iostream >
# include < queue >
# include < unordered_map >
# include < string >
using namespace std ;
while (! q . empty () )
{
char front = q . front () ;
q . pop () ;
if ( frequencyMap [ front ] == 1)
return front ;
}
return ’ ’;
}
int main ()
{
string input ;
cout << " Enter a string : " ;
getline ( cin , input ) ;
return 0;
}
Output 1:
Enter a string: geeky
The first non-repeating character is: g
Output 2:
Enter a string: aabbcc
No non-repeating character found.
3 Linked List
3.1 Reverse a Linked List
Algorithm:
18
1. Initialize three pointers: prev, curr, and next.
2. Traverse the linked list, and for each node:
Code:
# include < iostream >
using namespace std ;
struct ListNode
{
int val ;
ListNode * next ;
ListNode ( int x ) : val ( x ) , next ( NULL ) {}
};
return prev ;
}
int main ()
{
ListNode * head = createNode (1) ;
head - > next = createNode (2) ;
19
head - > next - > next = createNode (3) ;
head - > next - > next - > next = createNode (4) ;
head - > next - > next - > next - > next = createNode (5) ;
return 0;
}
Output 1:
Original Linked List: 1 2 3 4 5
Reversed Linked List: 5 4 3 2 1
Output 2:
Original Linked List: 10 20 30 40
Reversed Linked List: 40 30 20 10
struct ListNode
{
int val ;
ListNode * next ;
ListNode ( int x ) : val ( x ) , next ( NULL ) {}
};
20
while ( l1 != NULL && l2 != NULL )
{
if ( l1 - > val < l2 - > val )
{
current - > next = l1 ;
l1 = l1 - > next ;
}
else
{
current - > next = l2 ;
l2 = l2 - > next ;
}
current = current - > next ;
}
if ( l1 != NULL )
current - > next = l1 ;
else
current - > next = l2 ;
int main ()
{
int n1 , n2 ;
21
{
l2 = newNode ;
tail2 = l2 ;
}
else
{
tail2 - > next = newNode ;
tail2 = tail2 - > next ;
}
}
return 0;
}
Output 1:
Enter size of first linked list: 4
1 3 5 7
Enter size of second linked list: 3
2 4 6
Merged sorted linked list: 1 2 3 4 5 6 7
Output 2:
Enter size of first linked list: 3
2 6 8
Enter size of second linked list: 4
1 3 5 7
Merged sorted linked list: 1 2 3 5 6 7 8
3. Reverse the second half of the linked list starting from slow.
4. Compare the first half of the linked list with the reversed second half:
• Traverse from the head and compare each node with the corresponding node in the reversed second half.
5. If all nodes match, the linked list is a palindrome. Otherwise, it’s not.
6. Restore the second half of the linked list (optional, to preserve the original list).
7. Return the result.
Time Complexity:
• Best case: O(n) (if the list is already a palindrome and we traverse it once)
• Worst case: O(n) (we traverse the list once to find the middle and once to compare the two halves)
• Average case: O(n) (linear time complexity)
Space Complexity:
22
# include < iostream >
using namespace std ;
struct ListNode
{
int val ;
ListNode * next ;
ListNode ( int x ) : val ( x ) , next ( NULL ) {}
};
return prev ;
}
return true ;
}
int main ()
{
int n ;
cout << " Enter size of linked list : " ;
23
cin >> n ;
if ( isPalindrome ( head ) )
cout << " The linked list is a palindrome . " << endl ;
else
cout << " The linked list is not a palindrome . " << endl ;
return 0;
}
Output 1:
Enter size of linked list: 5
1 2 3 2 1
The linked list is a palindrome.
Output 2:
Enter size of linked list: 4
1 2 3 4
The linked list is not a palindrome.
24
Date: 5-12-24
4 Trees
4.1 Inorder Traversal
Algorithm (Recursive):
1. Start at the root node of the tree.
2. Traverse the left subtree in an inorder manner (recursively).
3. Visit the current node (process its value).
struct Node
{
int val ;
Node * left ;
Node * right ;
Node ( int x ) : val ( x ) , left ( NULL ) , right ( NULL ) {}
};
Node * createTree ( vector < int > & nodes , int & index , int n )
{
if ( index >= n || nodes [ index ] == -1)
return NULL ;
return root ;
}
int main ()
{
int n ;
25
cout << " Enter the number of nodes in the binary tree : " ;
cin >> n ;
int index = 0;
Node * root = createTree ( nodes , index , n ) ;
return 0;
}
Output 1:
Enter the number of nodes in the binary tree: 7
Enter the nodes of the binary tree (-1 for NULL): 1 2 3 -1 -1 4 5
Inorder Traversal of the binary tree: 2 1 4 3 5
Output 2:
Enter the number of nodes in the binary tree: 5
Enter the nodes of the binary tree (-1 for NULL): 10 5 15 -1 -1
Inorder Traversal of the binary tree: 5 10 15
struct Node
{
int val ;
Node * left ;
Node * right ;
26
Node ( int x ) : val ( x ) , left ( NULL ) , right ( NULL ) {}
};
return root ;
}
int main ()
{
int n ;
cout << " Enter the number of nodes in the binary tree : " ;
cin >> n ;
int nodes [ n ];
cout << " Enter the nodes of the binary tree ( -1 for NULL ) : " ;
for ( int i = 0; i < n ; i ++)
cin >> nodes [ i ];
int index = 0;
Node * root = createTree ( nodes , index , n ) ;
flatten ( root ) ;
return 0;
}
Output 1:
Enter the number of nodes in the binary tree: 7
27
Enter the nodes of the binary tree (-1 for NULL): 1 2 5 3 4 -1 6
Linked list representation: 1 2 3 4 5 6
Output 2:
Enter the number of nodes in the binary tree: 5
Enter the nodes of the binary tree (-1 for NULL): 10 5 15 -1 -1
Linked list representation: 10 5 15
struct Node
{
int val ;
Node * left ;
Node * right ;
Node ( int x ) : val ( x ) , left ( NULL ) , right ( NULL ) {}
};
while (! q . empty () )
{
auto front = q . front () ;
q . pop () ;
28
q . push ({ current - > left , hd - 1}) ;
if ( current - > right != NULL )
q . push ({ current - > right , hd + 1}) ;
}
return root ;
}
int main ()
{
int n ;
cout << " Enter the number of nodes in the binary tree : " ;
cin >> n ;
int nodes [ n ];
cout << " Enter the nodes of the binary tree ( -1 for NULL ) : " ;
for ( int i = 0; i < n ; i ++)
cin >> nodes [ i ];
int index = 0;
Node * root = createTree ( nodes , index , n ) ;
return 0;
}
Output 1:
Enter the number of nodes in the binary tree: 7
Enter the nodes of the binary tree (-1 for NULL): 20 8 22 5 3 -1 25
Bottom view of the binary tree: 5 3 22 25
Output 2:
Enter the number of nodes in the binary tree: 10
Enter the nodes of the binary tree (-1 for NULL): 1 2 3 4 5 6 7 -1 -1 8 9
Bottom view of the binary tree: 4 8 6 3 7
5 Operation On heaps
5.1 Heap Sort
Algorithm:
1. Build a max heap from the input array.
2. Swap the first element (largest) with the last element of the heap.
3. Reduce the heap size by 1 and heapify the root element to maintain the max heap property.
4. Repeat steps 2 and 3 until the heap size becomes 1.
Time Complexity:
29
• O(n log n): Building the heap takes O(n), and heapifying each element during the sorting process takes O(log n).
Space Complexity:
void heapify ( vector < int > & arr , int n , int i )
{
int largest = i ;
int left = 2 * i + 1;
int right = 2 * i + 2;
if ( largest != i )
{
swap ( arr [ i ] , arr [ largest ]) ;
heapify ( arr , n , largest ) ;
}
}
int main ()
{
int n ;
cout << " Enter the number of elements : " ;
cin >> n ;
heapSort ( arr ) ;
return 0;
}
Output 1:
Enter the number of elements: 5
Enter the elements: 4 10 3 5 1
Sorted array: 1 3 4 5 10
Output 2:
30
Enter the number of elements: 7
Enter the elements: 12 11 13 5 6 7 15
Sorted array: 5 6 7 11 12 13 15
vector < int > relativeSort ( vector < int > & arr1 , vector < int > & arr2 )
{
unordered_map < int , int > freq ;
vector < int > result ;
return result ;
}
int main ()
{
int n , m ;
cout << " Enter the size of the first array : " ;
cin >> n ;
vector < int > arr1 ( n ) ;
cout << " Enter the elements of the first array : " ;
for ( int i = 0; i < n ; i ++)
cin >> arr1 [ i ];
31
cout << " Enter the size of the second array : " ;
cin >> m ;
vector < int > arr2 ( m ) ;
cout << " Enter the elements of the second array : " ;
for ( int i = 0; i < m ; i ++)
cin >> arr2 [ i ];
return 0;
}
Output 1:
Enter the size of the first array: 7
Enter the elements of the first array: 2 1 2 5 7 1 9
Enter the size of the second array: 4
Enter the elements of the second array: 2 1 8 3
Resulting array after relative sorting: 2 2 1 1 5 7 9
Output 2:
Time Complexity:
• Push Operation: O(log n): Inserting an element involves heapify-up, which takes O(log n).
• Pop Operation: O(log n): Removing the root element involves heapify-down, which takes O(log n).
32
# include < iostream >
# include < vector >
using namespace std ;
class PriorityQueue
{
private :
vector < int > heap ;
if ( left < heap . size () && heap [ left ] > heap [ largest ])
largest = left ;
if ( right < heap . size () && heap [ right ] > heap [ largest ])
largest = right ;
if ( largest != i )
{
swap ( heap [ i ] , heap [ largest ]) ;
heapifyDown ( largest ) ;
}
}
public :
void push ( int x )
{
heap . push_back ( x ) ;
heapifyUp ( heap . size () - 1) ;
}
void pop ()
{
if ( heap . empty () )
{
cout << " Priority queue is empty ! " << endl ;
return ;
}
heap [0] = heap . back () ;
heap . pop_back () ;
heapifyDown (0) ;
}
int top ()
{
if ( heap . empty () )
{
cout << " Priority queue is empty ! " << endl ;
return -1;
}
return heap [0];
}
bool empty ()
{
return heap . empty () ;
}
};
int main ()
33
{
PriorityQueue pq ;
switch ( choice )
{
case 1:
cout << " Enter value to push : " ;
cin >> value ;
pq . push ( value ) ;
break ;
case 2:
pq . pop () ;
break ;
case 3:
cout << " Top element : " << pq . top () << endl ;
break ;
default :
cout << " Invalid operation ! " << endl ;
}
}
return 0;
}
Output 1:
Enter the number of operations: 6
Operations:
1. Push
2. Pop
3. Top
Enter operation: 1
Enter value to push: 10
Enter operation: 1
Enter value to push: 5
Enter operation: 1
Enter value to push: 20
Enter operation: 3
Top element: 20
Enter operation: 2
Enter operation: 3
Top element: 10
Output 2:
Enter the number of operations: 5
Operations:
1. Push
2. Pop
3. Top
Enter operation: 1
Enter value to push: 7
Enter operation: 1
Enter value to push: 15
Enter operation: 3
Top element: 15
Enter operation: 2
34
Enter operation: 3
Top element: 7
class HashTable
{
private :
vector < list < pair < int , int > > > table ;
int size ;
public :
HashTable ( int s )
{
size = s ;
table . resize ( size ) ;
}
35
}
}
table [ index ]. emplace_back ( key , value ) ;
}
void display ()
{
for ( int i = 0; i < size ; i ++)
{
cout << " Bucket " << i << " : " ;
for ( auto & pair : table [ i ])
cout << " ( " << pair . first << " , " << pair . second << " ) " ;
cout << endl ;
}
}
};
int main ()
{
int size , choice , key , value ;
cout << " Enter the size of the hash table : " ;
cin >> size ;
HashTable ht ( size ) ;
switch ( choice )
{
case 1:
cout << " Enter key and value to insert : " ;
cin >> key >> value ;
ht . insert ( key , value ) ;
break ;
case 2:
cout << " Enter key to search : " ;
cin >> key ;
value = ht . search ( key ) ;
if ( value != -1)
cout << " Value : " << value << endl ;
else
cout << " Key not found ! " << endl ;
break ;
case 3:
cout << " Enter key to remove : " ;
cin >> key ;
ht . remove ( key ) ;
36
break ;
case 4:
ht . display () ;
break ;
case 0:
cout << " Exiting . " << endl ;
break ;
default :
cout << " Invalid choice ! " << endl ;
}
} while ( choice != 0) ;
return 0;
}
Output 1:
Enter the size of the hash table: 5
Operations:
1. Insert
2. Search
3. Remove
4. Display
Enter your choice (0 to exit): 1
Enter key and value to insert: 10 100
Enter your choice (0 to exit): 1
Enter key and value to insert: 15 200
Enter your choice (0 to exit): 2
Enter key to search: 10
Value: 100
Enter your choice (0 to exit): 4
Bucket 0:
Bucket 1:
Bucket 2:
Bucket 3:
Bucket 4: (10, 100) (15, 200)
Enter your choice (0 to exit): 0
Exiting.
Output 2:
Enter the size of the hash table: 7
Operations:
1. Insert
2. Search
3. Remove
4. Display
Enter your choice (0 to exit): 1
Enter key and value to insert: 5 50
Enter your choice (0 to exit): 1
Enter key and value to insert: 12 120
Enter your choice (0 to exit): 4
Bucket 0:
Bucket 1:
Bucket 2:
Bucket 3:
Bucket 4:
Bucket 5: (5, 50)
Bucket 6: (12, 120)
Enter your choice (0 to exit): 3
Enter key to remove: 5
Enter your choice (0 to exit): 4
Bucket 0:
37
Bucket 1:
Bucket 2:
Bucket 3:
Bucket 4:
Bucket 5:
Bucket 6: (12, 120)
Enter your choice (0 to exit): 0
Exiting.
bool comparator ( const pair < int , int > &a , const pair < int , int > & b )
{
if ( a . second == b . second )
return a . first < b . first ;
return a . second > b . second ;
}
vector < pair < int , int > > freqVec ( freqMap . begin () , freqMap . end () ) ;
sort ( freqVec . begin () , freqVec . end () , comparator ) ;
arr = sortedArr ;
38
}
int main ()
{
int n ;
cout << " Enter the number of elements : " ;
cin >> n ;
s or tB yF r eq ue nc y ( arr ) ;
return 0;
}
Output 1:
Enter the number of elements: 8
Enter the elements: 4 5 6 5 4 3 3 3
Sorted array by frequency: 3 3 3 4 4 5 5 6
Output 2:
Enter the number of elements: 7
Enter the elements: 1 2 3 2 1 1 4
Sorted array by frequency: 1 1 1 2 2 3 4
39
{
unordered_set < int > elements ( arr . begin () , arr . end () ) ;
int longest = 0;
int main ()
{
int n ;
cout << " Enter the number of elements : " ;
cin >> n ;
return 0;
}
Output 1:
Enter the number of elements: 6
Enter the elements: 100 4 200 1 3 2
Length of the longest consecutive subsequence: 4
Output 2:
Enter the number of elements: 7
Enter the elements: 2 6 1 9 4 3 5
Length of the longest consecutive subsequence: 6
1. Check if the lengths of the two arrays are different. If they are, the arrays are not equal.
2. Use a hash map to count the frequency of each element in the first array.
3. Traverse the second array and decrement the frequency of each element in the hash map:
• If an element is not found or its count goes below zero, the arrays are not equal.
4. After processing the second array, check if all values in the hash map are zero. If they are, the arrays are equal.
5. Return the result.
Time Complexity:
• O(n):
– Building the frequency map takes O(n).
40
– Traversing the second array and checking the map also takes O(n).
Space Complexity:
• O(n): Space for the hash map.
Code:
# include < iostream >
# include < vector >
# include < unordered_map >
using namespace std ;
bool areArray sEqual ( vector < int > & arr1 , vector < int > & arr2 )
{
if ( arr1 . size () != arr2 . size () )
return false ;
int main ()
{
int n1 , n2 ;
cout << " Enter the size of the first array : " ;
cin >> n1 ;
vector < int > arr1 ( n1 ) ;
cout << " Enter elements of the first array : " ;
for ( int i = 0; i < n1 ; i ++)
cin >> arr1 [ i ];
cout << " Enter the size of the second array : " ;
cin >> n2 ;
vector < int > arr2 ( n2 ) ;
cout << " Enter elements of the second array : " ;
for ( int i = 0; i < n2 ; i ++)
cin >> arr2 [ i ];
return 0;
}
Output 1:
Enter the size of the first array: 5
Enter elements of the first array: 1 2 3 4 5
Enter the size of the second array: 5
Enter elements of the second array: 5 4 3 2 1
The arrays are equal.
Output 2:
Enter the size of the first array: 4
Enter elements of the first array: 1 2 3 4
Enter the size of the second array: 4
Enter elements of the second array: 1 2 2 4
The arrays are not equal.
41
Date: 12-12-2024
7 Sorting
7.1 Insertion Sort
Algorithm:
1. Iterate through the array from the second element to the last element.
2. For each element, store its value in a temporary variable.
3. Compare the temporary value with elements in the sorted portion of the array (elements to its left):
Time Complexity:
• Best Case: O(n): When the array is already sorted, only n − 1 comparisons are needed.
• Worst Case: O(n2 ): When the array is sorted in reverse order, the inner loop runs for every element.
• Average Case: O(n2 ): On average, elements are halfway out of place.
Space Complexity:
• O(1): Sorting is done in-place, requiring no extra memory.
Code:
# include < iostream >
# include < vector >
using namespace std ;
int main ()
{
int n ;
cout << " Enter the number of elements : " ;
cin >> n ;
insertionSort ( arr ) ;
42
cout << endl ;
return 0;
}
Output 1:
Enter the number of elements: 5
Enter the elements: 12 11 13 5 6
Sorted array: 5 6 11 12 13
Output 2:
Enter the number of elements: 4
Enter the elements: 20 10 40 30
Sorted array: 10 20 30 40
int hoarePa rtition ( vector < int >& arr , int low , int high ) {
int pivot = arr [ low ];
int i = low - 1;
int j = high + 1;
while ( true ) {
do {
i ++;
} while ( arr [ i ] < pivot ) ;
do {
j - -;
43
} while ( arr [ j ] > pivot ) ;
if ( i >= j ) {
return j ;
}
swap ( arr [ i ] , arr [ j ]) ;
}
}
void quickSort ( vector < int >& arr , int low , int high ) {
if ( low < high ) {
int p = hoar ePartit ion ( arr , low , high ) ;
quickSort ( arr , low , p ) ;
quickSort ( arr , p + 1 , high ) ;
}
}
int main () {
int n ;
cout << " Enter the number of elements : " ;
cin >> n ;
quickSort ( arr , 0 , n - 1) ;
return 0;
}
Output 1:
44
Code:
# include < iostream >
# include < vector >
using namespace std ;
void merge ( vector < int >& arr , int left , int mid , int right ) {
int n1 = mid - left + 1;
int n2 = right - mid ;
int i = 0 , j = 0 , k = left ;
while ( i < n1 && j < n2 )
{
if ( leftArr [ i ] <= rightArr [ j ])
arr [ k ++] = leftArr [ i ++];
else
arr [ k ++] = rightArr [ j ++];
}
while ( i < n1 )
arr [ k ++] = leftArr [ i ++];
while ( j < n2 )
arr [ k ++] = rightArr [ j ++];
}
void mergeSort ( vector < int >& arr , int left , int right ) {
if ( left < right ) {
int mid = left + ( right - left ) / 2;
int main () {
int n ;
cout << " Enter the number of elements : " ;
cin >> n ;
mergeSort ( arr , 0 , n - 1) ;
return 0;
}
Output 1:
Enter the number of elements: 5
Enter the elements: 12 11 13 5 6
Sorted array: 5 6 11 12 13
Output 2:
Enter the number of elements: 6
Enter the elements: 38 27 43 3 9 82
45
Sorted array: 3 9 27 38 43 82
8 Recursion
8.1 Fibonacci Sequence using recursion
Algorithm:
1. Define a recursive function fibonacci(n):
• Base cases:
– If n = 0, return 0.
– If n = 1, return 1.
• Recursive case: Return the sum of fibonacci(n - 1) and fibonacci(n - 2).
2. In the main function:
• Take the number of terms (n) as input.
• Print the Fibonacci sequence by calling the fibonacci function iteratively for indices 0 to n − 1.
Time Complexity:
• O(2n ): Each call splits into two further calls, resulting in exponential growth of computations.
Space Complexity:
• O(n): Due to recursive function call stack.
Code:
# include < iostream >
using namespace std ;
int main ()
{
int n ;
cout << " Enter the number of terms : " ;
cin >> n ;
if ( n <= 0)
{
cout << " Number of terms must be positive . " << endl ;
return 0;
}
return 0;
}
Output 1:
Enter the number of terms: 5
Fibonacci Sequence: 0 1 1 2 3
Output 2:
Enter the number of terms: 8
Fibonacci Sequence: 0 1 1 2 3 5 8 13
46
8.2 Fibonacci Sequence using Memo Table
Algorithm:
1. Create a memo table (array) to store Fibonacci numbers, initialized with -1.
2. Define a recursive function fibonacci(n):
• Base cases:
– If n = 0, return 0.
– If n = 1, return 1.
• If the Fibonacci number for n is already computed (i.e., memo[n] != -1), return memo[n].
• Otherwise, compute fibonacci(n - 1) + fibonacci(n - 2), store it in memo[n], and return the result.
3. In the main function:
• Take the number of terms (n) as input.
• Print the Fibonacci sequence by calling the fibonacci function iteratively for indices 0 to n − 1.
Time Complexity:
• O(n): Each Fibonacci number is computed only once and stored in the memo table.
Space Complexity:
if ( memo [ n ] != -1)
return memo [ n ];
int main ()
{
int n ;
cout << " Enter the number of terms : " ;
cin >> n ;
if ( n <= 0)
{
cout << " Number of terms must be positive . " << endl ;
return 0;
}
return 0;
}
Output 1:
47
Enter the number of terms: 5
Fibonacci Sequence: 0 1 1 2 3
Output 2:
Enter the number of terms: 8
Fibonacci Sequence: 0 1 1 2 3 5 8 13
48
Date: 19-12-2024
• O(2n − 1): Each recursive call splits into two smaller recursive calls, doubling the work with each additional disk.
Space Complexity:
• O(n): Due to the recursive call stack.
Code:
# include < iostream >
using namespace std ;
int main ()
{
int n ;
cout << " Enter the number of disks : " ;
cin >> n ;
if ( n <= 0)
{
cout << " Number of disks must be positive . " << endl ;
return 0;
}
cout << " The sequence of moves to solve Tower of Hanoi is :\ n " ;
towerOfHanoi (n , ’A ’ , ’C ’ , ’B ’) ;
return 0;
}
Output 1:
Enter the number of disks: 2
The sequence of moves to solve Tower of Hanoi is:
Move disk 1 from A to B
Move disk 2 from A to C
Move disk 1 from B to C
49
Output 2:
Enter the number of disks: 3
The sequence of moves to solve Tower of Hanoi is:
Move disk 1 from A to C
Move disk 2 from A to B
Move disk 1 from C to B
Move disk 3 from A to C
Move disk 1 from B to A
Move disk 2 from B to C
Move disk 1 from A to C
int main () {
int n ;
cout << " Enter the number of elements : " ;
cin >> n ;
if ( n <= 0)
{
cout << " Number of elements must be positive . " << endl ;
return 0;
}
50
Output 1:
Enter the number of elements: 5
Enter the elements: 1 2 3 4 5
Sum of array elements: 15
Output 2:
Enter the number of elements: 4
Enter the elements: 10 20 30 40
Sum of array elements: 100
9 Graphs
9.1 Depth First Traversal
Algorithm:
1. Use a recursive function to perform Depth First Search (DFS).
2. Define a function DFS(node, visited, graph):
• Base Case: If the node has already been visited, return.
• Recursive Case:
(a) Mark the current node as visited.
(b) Print the current node or store it in a result list.
(c) Recursively call DFS for all unvisited neighbors of the current node.
3. For disconnected graphs:
• Iterate through all nodes and perform DFS for each unvisited node.
Time Complexity:
• O(V + E): V is the number of vertices, and E is the number of edges. Each vertex and edge is visited once.
Space Complexity:
• O(V ): Due to the recursion stack and visited array.
Code:
# include < iostream >
# include < vector >
# include < list >
using namespace std ;
void DFS ( int node , vector < bool > & visited , const vector < list < int > > & graph )
{
visited [ node ] = true ;
cout << node << " " ;
int main ()
{
int V , E ;
cout << " Enter the number of vertices : " ;
cin >> V ;
cout << " Enter the number of edges : " ;
cin >> E ;
51
{
int u , v ;
cin >> u >> v ;
graph [ u ]. push_back ( v ) ;
graph [ v ]. push_back ( u ) ;
}
cout << " Depth First Traversal starting from node 0: " ;
for ( int i = 0; i < V ; i ++)
if (! visited [ i ])
DFS (i , visited , graph ) ;
cout << endl ;
return 0;
}
Output 1:
Enter the number of vertices: 5
Enter the number of edges: 4
Enter the edges (u v):
0 1
0 2
1 3
1 4
Depth First Traversal starting from node 0: 0 1 3 4 2
Output 2:
Enter the number of vertices: 6
Enter the number of edges: 5
Enter the edges (u v):
0 1
0 2
1 3
3 4
4 5
Depth First Traversal starting from node 0: 0 1 3 4 5 2
52
Date: 26-12-2024
cout << " Shortest distances from source " << source << " : " << endl ;
for ( int i = 0; i < V ; i ++)
if ( distance [ i ] == INF )
cout << " Vertex " << i << " : INF " << endl ;
else
53
cout << " Vertex " << i << " : " << distance [ i ] << endl ;
}
int main ()
{
int V , E ;
cout << " Enter the number of vertices : " ;
cin >> V ;
cout << " Enter the number of edges : " ;
cin >> E ;
int source ;
cout << " Enter the source vertex : " ;
cin >> source ;
return 0;
}
Output 1:
Enter the number of vertices: 5
Enter the number of edges: 6
Enter the edges (u, v, weight):
0 1 2
0 2 4
1 2 1
1 3 7
2 4 3
3 4 1
Enter the source vertex: 0
Shortest distances from source 0:
Vertex 0: 0
Vertex 1: 2
Vertex 2: 3
Vertex 3: 9
Vertex 4: 6
Output 2:
Enter the number of vertices: 4
Enter the number of edges: 4
Enter the edges (u, v, weight):
0 1 1
1 2 2
0 2 4
2 3 1
Enter the source vertex: 0
Shortest distances from source 0:
Vertex 0: 0
Vertex 1: 1
Vertex 2: 3
Vertex 3: 4
54
9.3 Cycle Detection: Undirected Graph
Algorithm:
1. Represent the graph using an adjacency matrix graph.
2. Use a visited array to track visited nodes.
3. Perform DFS:
• If a visited node is encountered that is not the parent, a cycle is detected.
4. Repeat the process for all components of the graph.
Time Complexity:
• O(V 2 ): Adjacency matrix requires checking all nodes for edges.
Space Complexity:
• O(V ): Due to the visited and recStack arrays.
Code:
# include < iostream >
# include < cstring >
using namespace std ;
bool dfsUndirected ( int node , int parent , int graph [ MAX ][ MAX ] , bool visited [] , int n )
{
visited [ node ] = true ;
int main ()
{
int n , m ;
cout << " Enter the number of nodes and edges : " ;
cin >> n >> m ;
55
if ( h a s C y c l e U n d i r e c t e d (n , graph ) )
cout << " Cycle detected in the undirected graph . " << endl ;
else
cout << " No cycle detected in the undirected graph . " << endl ;
return 0;
}
Output 1:
Enter the number of nodes and edges: 4 3
Enter the edges (u v):
0 1
1 2
2 0
Cycle detected in the undirected graph.
Output 2:
Enter the number of nodes and edges: 4 3
Enter the edges (u v):
0 1
1 2
2 3
No cycle detected in the undirected graph.
bool dfsDirected ( int node , int graph [ MAX ][ MAX ] , bool visited [] , bool recStack [] , int n )
{
visited [ node ] = true ;
recStack [ node ] = true ;
56
{
return true ;
}
}
else if ( recStack [ neighbor ])
return true ;
}
int main ()
{
int n , m ;
cout << " Enter the number of nodes and edges : " ;
cin >> n >> m ;
if ( h a s C y c l e D i r e c t e d (n , graph ) )
cout << " Cycle detected in the directed graph . " << endl ;
else
cout << " No cycle detected in the directed graph . " << endl ;
return 0;
}
Output 1:
57
10 Dynamic Programming
10.1 Binomial Co efficient
Algorithm:
1. Define a DP table dp[n + 1][k + 1]:
dp[i][j] stores C(i, j), the number of ways to choose j items from i items.
return dp [ n ][ k ];
}
int main ()
{
int n , k ;
cout << " Enter the values of n and k : " ;
cin >> n >> k ;
if ( k > n )
{
58
cout << " Invalid input : k cannot be greater than n . " << endl ;
return 0;
}
cout << " Binomial Coefficient C ( " << n << " , " << k << " ) = " << b i n o m i a l C o e f f i c i e n t (n , k ) << endl ;
return 0;
}
Output 1:
Enter the values of n and k: 5 2
Binomial Coefficient C(5, 2) = 10
Output 2:
Enter the values of n and k: 6 3
Binomial Coefficient C(6, 3) = 20
dp[i][j] stores the length of the longest common substring ending at indices i − 1 and j − 1.
59
dp [ i ][ j ] = 0;
return maxLen ;
}
int main ()
{
char A [ MAX ] , B [ MAX ];
cout << " Enter the first string : " ;
cin >> A ;
cout << " Enter the second string : " ;
cin >> B ;
return 0;
}
Output 1:
Enter the first string: abcde
Enter the second string: abfce
Length of Longest Common Substring: 2
Output 2:
Enter the first string: abcxyz
Enter the second string: xyzabc
Length of Longest Common Substring: 3
60
for ( int i = 0; i < n ; i ++)
dp [1 << i ][ i ] = 0;
return result ;
}
int main ()
{
int n ;
cout << " Enter the number of cities : " ;
cin >> n ;
return 0;
}
Output 1:
Enter the number of cities: 4
Enter the distance matrix:
0 10 15 20
10 0 35 25
15 35 0 30
20 25 30 0
The minimum cost of the Travelling Salesman Problem is: 80
Output 2:
Enter the number of cities: 3
Enter the distance matrix:
0 1 2
1 0 3
2 3 0
The minimum cost of the Travelling Salesman Problem is: 6
61