ACA Lab Doc
ACA Lab Doc
1MS21EC127
1. Start with two pointers, start and end, initialized to the beginning of the array.
2. Maintain a variable currentSum to store the sum of elements between the two pointers.
o If currentSum exceeds the target S, move the start pointer to the right until
currentSum is less than or equal to S.
Code:
#include <iostream>
#include <vector>
currentSum += arr[end];
currentSum -= arr[start];
start++;
if (currentSum == S) {
1
return {};
int main()
{
if (!result.empty()) {
cout << "Subarray found from index " << result[0] << " to " << result[1] << endl;
} else {
cout << "No subarray with the given sum found." << endl;
return 0;
1. Input
Array: [1, 2, 3, 7, 5]
Target Sum: 12
Output
Subarray found from index 2 to 4
Algorithm:
1. Use two pointers, i for the first array and j for the second array.
2
Code:
#include <iostream>
#include <vector>
vector<int> mergedArray;
int i = 0, j = 0;
mergedArray.push_back(arr1[i++]);
} else {
mergedArray.push_back(arr2[j++]);
mergedArray.push_back(arr1[i++]);
mergedArray.push_back(arr2[j++]);
return mergedArray;
int main() {
3
Input and Output:
Input 1:
Array 1: [1, 3, 5]
Array 2: [2, 4, 6]
Output 1:
Merged Array: 1 2 3 4 5 6
Input 2:
Array 1: [1, 2, 3]
Array 2: [4, 5, 6]
Output 2:
Merged Array: 1 2 3 4 5 6
3. Inversion of Array
Algorithm:
o Count the inversions in the left half, right half, and while merging.
o During merge, count pairs where the left element is greater than the right element.
Code:
#include <iostream>
#include <vector>
temp[k++] = arr[i++];
} else {
temp[k++] = arr[j++];
4
inversions += (mid - i + 1);
arr[i] = temp[k];
return inversions;
int inversions = 0;
return inversions;
int main() {
cout << "Number of inversions: " << countInversions(arr, 0, arr.size() - 1) << endl;
return 0;
Input 1:
Array: [8, 4, 2, 1]
Output 1:
Number of inversions: 6
Input 2:
5
Array: [3, 1, 2]
Output 2:
Number of inversions: 2
4. Parenthesis Checker
Algorithm:
Code:
#include <iostream>
#include <stack>
bool isBalanced(string s) {
stack<char> st;
for (char c : s) {
st.push(c);
} else {
st.pop();
} else {
return false;
6
}
return st.empty();
int main() {
string s = "{[()]}";
s = "{[(])}";
return 0;
Input 1:
String: {[()]}
Output 1:
Balanced
Input 2:
String: {[(])}
Output 2:
Not Balanced
7
Code:
#include <iostream>
#include <queue>
class StackUsingQueues {
public:
void push(int x) {
q2.push(x);
while (!q1.empty()) {
q2.push(q1.front());
q1.pop();
swap(q1, q2);
void pop() {
if (!q1.empty()) q1.pop();
int top() {
bool isEmpty() {
return q1.empty();
};
int main() {
StackUsingQueues stack;
stack.push(1);
stack.push(2);
stack.push(3);
8
stack.pop();
cout << "Is stack empty? " << (stack.isEmpty() ? "Yes" : "No") << endl;
return 0;
Input:
Output:
Top element: 3
Top element: 2
Is stack empty? No
Algorithm:
o Remove characters from the front of the queue while their count in the map is
greater than 1.
Code:
#include <iostream>
#include <queue>
#include <unordered_map>
9
void firstNonRepeating(string stream) {
queue<char> q;
count[c]++;
q.push(c);
q.pop();
if (q.empty()) {
} else {
int main() {
firstNonRepeating(stream);
stream = "xyzxyz";
firstNonRepeating(stream);
return 0;
Input 1:
Stream: aabc
Output 1:
a -1 b b
Input 2:
Stream: xyzxyz
10
Output 2:
x x x -1 -1 -1
1. Initialize three pointers: prev as NULL, current as the head, and next as NULL.
Code:
#include <iostream>
struct Node {
int data;
Node* next;
};
next = current->next;
current->next = prev;
prev = current;
current = next;
return prev;
11
void printList(Node* head) {
head = head->next;
int main() {
printList(head);
head = reverseLinkedList(head);
printList(head);
return 0;
Input:
Output:
Original List: 1 2 3 4
Reversed List: 4 3 2 1
Algorithm:
1. Create a dummy node to serve as the starting point of the merged list.
12
3. Traverse both lists:
o Append the smaller node to current and move the pointer in that list forward.
4. Append any remaining nodes from either list to the merged list.
5. Return the merged list starting from the node after the dummy node.
Code:
#include <iostream>
struct Node {
int data;
Node* next;
};
Node dummy(0);
current->next = l1;
l1 = l1->next;
} else {
current->next = l2;
l2 = l2->next;
current = current->next;
return dummy.next;
13
void printList(Node* head) {
head = head->next;
int main() {
printList(l1);
printList(l2);
printList(mergedList);
return 0;
Input:
Output:
Merged List: 1 2 3 4 5 6
14
8. Check if Linked List is a Palindrome
Algorithm:
1. Use two pointers (slow and fast) to find the middle of the list.
3. Compare the first half and the reversed second half node by node.
Code:
#include <iostream>
struct Node {
int data;
Node* next;
};
head->next = prev;
prev = head;
head = next;
return prev;
slow = slow->next;
15
fast = fast->next->next;
slow = reverseList(slow);
firstHalf = firstHalf->next;
secondHalf = secondHalf->next;
return true;
int main() {
return 0;
Input:
Output:
Palindrome
Input:
Output:
Not Palindrome
16
9. Inorder Traversal of a Binary Tree
Algorithm:
Code:
#include <iostream>
struct Node {
int data;
Node* left;
Node* right;
};
inorderTraversal(root->left);
inorderTraversal(root->right);
int main() {
inorderTraversal(root);
return 0; }
17
Input and Output:
Input:
Tree:
/\
2 3
/\
4 5
Output:
Inorder Traversal: 4 2 5 1 3
Algorithm:
3. Update the left and right pointers of the current node to establish the doubly linked list
connections.
Code:
#include <iostream>
struct Node {
int data;
Node* left;
Node* right;
};
18
if (prev == NULL) {
head = root;
} else {
prev->right = root;
root->left = prev;
prev = root;
head = head->right;
int main() {
printDoublyLinkedList(head);
return 0;
19
Input and Output:
Input:
Tree:
/\
2 3
/\
4 5
Output:
o Assign HD = 0 to the root, HD - 1 to the left child, and HD + 1 to the right child.
3. Use a map to store the last node seen at each horizontal distance.
Code:
#include <iostream>
#include <queue>
#include <map>
struct Node {
int data;
Node* left;
Node* right;
};
20
map<int, int> hdMap;
queue<pair<Node*, int>> q;
q.push({root, 0});
while (!q.empty()) {
q.pop();
hdMap[hd] = node->data;
int main() {
bottomView(root);
return 0;
21
Input and Output:
Input:
Tree:
/ \
2 3
/\ /\
4 56 7
Output:
Bottom View: 4 2 6 3 7
2. Extract the largest element (root of the heap) and place it at the end of the array.
Code:
#include <iostream>
#include <vector>
int largest = i;
int left = 2 * i + 1;
int right = 2 * i + 2;
largest = left;
largest = right;
22
if (largest != i) {
swap(arr[i], arr[largest]);
heapify(arr, n, largest);
int n = arr.size();
heapify(arr, n, i);
swap(arr[0], arr[i]);
heapify(arr, i, 0);
int main() {
printArray(arr1);
heapSort(arr1);
printArray(arr1);
printArray(arr2);
heapSort(arr2);
23
printArray(arr2);
return 0;
Input 1:
Array: 4, 10, 3, 5, 1
Output 1:
Sorted Array: 1 3 4 5 10
Input 2:
Output 2:
Sorted Array: 5 10 15 20 30 40
1. Use a hash map to store the frequency of each element in the first array (arr1), which helps
in tracking how many times each element appears.
2. Iterate through the second array (arr2) and collect the elements from arr1 based on their
order in arr2, inserting each element according to its frequency in arr1.
3. Identify the elements in arr1 that are not present in arr2 and sort these remaining elements
in ascending order.
4. Append the sorted remaining elements to the result array, which already contains the
elements sorted based on the order in arr2.
Code:
#include <iostream>
#include <unordered_map>
#include <vector>
#include <algorithm>
freq[num]++;
24
vector<int> result;
result.push_back(num);
freq[num]--;
freq.erase(num);
vector<int> remaining;
while (count--)
remaining.push_back(num);
sort(remaining.begin(), remaining.end());
return result;
int main() {
printArray(sorted1);
25
printArray(sorted2);
return 0;
Input 1:
Array 1: 2, 1, 2, 5, 7, 1, 9, 3, 6, 8, 8
Array 2: 2, 1, 8, 3
Output 1:
Sorted Array: 2 2 1 1 8 8 3 5 6 7 9
Input 2:
Array 1: 5, 3, 1, 2, 2, 6, 7
Array 2: 2, 3
Output 2:
Sorted Array: 2 2 3 1 5 6 7
Code:
#include <iostream>
#include <queue>
int main() {
priority_queue<int> pq;
26
for (int num : elements1)
pq.push(num);
while (!pq.empty()) {
pq.pop();
pq.push(num);
while (!pq.empty()) {
pq.pop();
return 0;
Input 1:
Output 1:
Priority Queue: 30 20 15 10 5
Input 2:
Output 2:
Priority Queue: 40 35 25 10
27
15.Implement Hash Table
Algorithm:
1. Define a Hash Table: Create an array of linked lists (or arrays) to store key-value pairs.
2. Hash Function: Define a hash function to map a key to an index in the hash table.
3. Insert Operation: Insert key-value pairs into the hash table by hashing the key and placing
the pair in the corresponding bucket.
4. Search Operation: Search for a key by hashing it and checking the corresponding bucket for
the value.
Code:
#include <iostream>
#include <list>
class HashTable {
private:
public:
table[index].push_back(make_pair(key, value));
if (pair.first == key) {
return pair.second;
28
return -1;
void display() {
if (!table[i].empty()) {
cout << "[" << pair.first << ", " << pair.second << "] ";
};
int main() {
HashTable ht;
ht.insert(1, 100);
ht.insert(11, 200);
ht.insert(21, 300);
ht.display();
cout << "Value for key 11: " << ht.search(11) << endl;
cout << "Value for key 21: " << ht.search(21) << endl;
cout << "Value for key 5 (not inserted): " << ht.search(5) << endl;
return 0;
Input/Output:
Input 1:
Output 1:
29
Index 0: [21, 300]
Input 2:
Output 2:
1. Count Frequencies: Traverse the array and count the frequency of each element using a
simple array or a frequency counter array.
2. Group Elements by Frequency: Store elements with the same frequency together.
3. Sort by Frequency: Sort the elements first by frequency in descending order, and in case of
ties, by element value in ascending order.
4. Rebuild Sorted Array: Rebuild the array based on sorted frequencies and element values.
Code:
#include <iostream>
#include <vector>
#include <algorithm>
int n = arr.size();
30
for (int num : arr)
freq[num]++;
if (freq[i] > 0) {
freqVec.push_back({i, freq[i]});
if (a.second == b.second)
});
arr.clear();
arr.push_back(p.first);
int main() {
printArray(arr1);
sortByFrequency(arr1);
31
cout << "Sorted Array 1 by Frequency: ";
printArray(arr1);
printArray(arr2);
sortByFrequency(arr2);
printArray(arr2);
return 0;
Input 1:
Array: 3, 3, 3, 2, 2, 1
Output 1:
Sorted Array: 3 3 3 2 2 1
Input 2:
Array: 4, 5, 6, 6, 5, 4, 4
Output 2:
Sorted Array: 4 4 4 5 5 6 6
1. Sort the Array: First, sort the array to bring consecutive elements together.
2. Find Consecutive Sequences: Traverse the sorted array and keep track of the longest
subsequence where consecutive numbers appear.
3. Check Consecutive Numbers: For each number, check if the next number is consecutive (i.e.,
num + 1).
4. Track Maximum Length: Track the length of the current consecutive subsequence and
update the maximum length.
Code:
#include <iostream>
#include <vector>
32
#include <algorithm>
if (arr.empty()) return 0;
sort(arr.begin(), arr.end());
if (arr[i] == arr[i - 1] + 1) {
current_len++;
} else {
current_len = 1;
return longest;
int main() {
return 0;
Input 1:
Output 1:
33
Longest Consecutive Subsequence Length: 4
Input 2:
Array: 10, 5, 1, 3, 9, 2
Output 2:
1. Check Length: First, check if the arrays have the same length.
4. Return Result: If all elements are equal, return true; otherwise, return false.
Code:
#include <iostream>
#include <vector>
#include <algorithm>
sort(arr1.begin(), arr1.end());
sort(arr2.begin(), arr2.end());
return true;
int main() {
34
cout << "Are Array 1 and Array 2 equal? "
return 0;
Input 1:
Array 1: 1, 2, 3, 4, 5
Array 2: 5, 4, 3, 2, 1
Output 1:
Input 2:
Array 1: 1, 2, 3, 4, 5
Array 3: 1, 2, 3, 6
Output 2:
Algorithm:
1. Choose a Pivot: Select a pivot element from the array. Typically, the last element is chosen as
the pivot.
2. Partition the Array: Rearrange the array so that elements less than the pivot are on the left
and elements greater than the pivot are on the right.
3. Recursively Apply Quick Sort: Recursively apply the quick sort on the left and right sub-
arrays formed by the partition.
4. Base Case: If the sub-array has one or zero elements, it's already sorted.
Code:
#include <iostream>
#include <vector>
35
using namespace std;
int i = low - 1;
i++;
swap(arr[i], arr[j]);
return i + 1;
quickSort(arr, pi + 1, high);
int main() {
printArray(arr1);
36
cout << "Sorted Array 1: ";
printArray(arr1);
printArray(arr2);
printArray(arr2);
return 0;
Input 1:
Array: 10, 7, 8, 9, 1, 5
Output 1:
Sorted Array: 1 5 7 8 9 10
Input 2:
Output 2:
Sorted Array: 5 6 7 11 12 13
Algorithm:
1. Start from the Second Element: Consider the second element in the array as the key.
2. Compare and Shift: Compare the key with the element before it and shift all greater
elements one position to the right.
3. Insert the Key: Insert the key at its correct position in the sorted part of the array.
4. Repeat for All Elements: Repeat this process for all elements until the entire array is sorted.
Code:
#include <iostream>
#include <vector>
37
void insertionSort(vector<int>& arr) {
int n = arr.size();
int j = i - 1;
arr[j + 1] = arr[j];
j = j - 1;
arr[j + 1] = key;
int main() {
printArray(arr1);
insertionSort(arr1);
printArray(arr1);
printArray(arr2);
insertionSort(arr2);
printArray(arr2);
38
return 0;
Input 1:
Output 1:
Sorted Array: 5 6 11 12 13
Input 2:
Array: 5, 9, 2, 8, 1, 3
Output 2:
Sorted Array: 1 2 3 5 8 9
1. Divide the Array: Recursively divide the array into two halves until each sub-array contains a
single element.
2. Merge Sub-arrays: Merge the sub-arrays by comparing their elements and placing the
smaller element first.
3. Repeat the Merge: Continue the merging process until all sub-arrays are merged into a single
sorted array.
4. Base Case: When the sub-array has only one element, it is already sorted.
Code:
#include <iostream>
#include <vector>
39
for (int i = 0; i < n2; i++)
int i = 0, j = 0, k = left;
arr[k] = leftArr[i];
i++;
} else {
arr[k] = rightArr[j];
j++;
k++;
arr[k] = leftArr[i];
i++;
k++;
arr[k] = rightArr[j];
j++;
k++;
40
}
int main() {
printArray(arr1);
printArray(arr1);
printArray(arr2);
printArray(arr2);
return 0;
Input 1:
Output 1:
Sorted Array: 3 9 10 27 38 43 82
Input 2:
Output 2:
Sorted Array: 5 6 11 12 13
41
22. Fibonacci Sequence
Without Using Memo Table (Recursion):
Algorithm:
2. Recursive Calls: For any other value of n, return the sum of the Fibonacci numbers for n-1
and n-2.
3. Repeat: Keep calling the function recursively until reaching the base cases.
Code:
#include <iostream>
int fibonacci(int n) {
if (n <= 1)
return n;
int main() {
int n1 = 6;
int n2 = 10;
cout << "Fibonacci of " << n1 << ": " << fibonacci(n1) << endl;
cout << "Fibonacci of " << n2 << ": " << fibonacci(n2) << endl;
return 0;
Input:
Fibonacci of 6 and 10
Output:
Fibonacci of 6: 8
Fibonacci of 10: 55
42
With Memo Table (Memoization):
Algorithm:
3. Recursive Calls: For any other value of n, if it has already been computed, return the stored
value; otherwise, compute it and store it.
Code:
#include <iostream>
#include <vector>
if (n <= 1)
return n;
if (dp[n] != -1)
return dp[n];
return dp[n];
int main() {
int n1 = 6;
int n2 = 10;
cout << "Fibonacci of " << n1 << ": " << fibonacci(n1, dp1) << endl;
cout << "Fibonacci of " << n2 << ": " << fibonacci(n2, dp2) << endl;
return 0;
Input:
Fibonacci of 6 and 10
43
Output:
Fibonacci of 6: 8
Fibonacci of 10: 55
1. Base Case: If there is only one disk, move it from the source rod to the destination rod.
2. Recursive Case: Move n-1 disks from the source to the auxiliary rod, then move the nth disk
to the destination rod, and finally move the n-1 disks from the auxiliary rod to the
destination rod.
Code:
#include <iostream>
if (n == 1) {
cout << "Move disk 1 from " << source << " to " << destination << endl;
return;
cout << "Move disk " << n << " from " << source << " to " << destination << endl;
int main() {
int n1 = 3;
int n2 = 4;
cout << "Tower of Hanoi for " << n1 << " disks:" << endl;
cout << "\nTower of Hanoi for " << n2 << " disks:" << endl;
return 0;
44
Input and Output (Tower of Hanoi):
Input:
Output:
45