0% found this document useful (0 votes)
29 views17 pages

Akshat Daa Assignment

Uploaded by

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

Akshat Daa Assignment

Uploaded by

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

DEPARTMENT OF

COMPUTER SCIENCE & ENGINEERING


Experiment 9th (Fast Learner)

Student Name: Akshat Shukla UID: 22BCS12484


Branch: BE CSE Section/Group: 801-A
Semester: 5th Date of Performance: 22-10-24
Subject Name: DAA Subject Code: 22CSH-311

1. Problem 1: Reverse a Linked List

Aim: Given the pointer to the head node of a linked list, change the next pointers of the
nodes so that their order is reversed. The head pointer given may be null meaning that the
initial list is empty.

Objective: Given the head of a singly linked list, reverse the pointers between nodes so that
the list is reversed.

Algorithm:

1. Initialize three pointers: prev (initially NULL), current (points to the head), and next
(initially NULL).
2. Traverse the list. For each node:

 Save the next node (next = current->next).


 Reverse the pointer of the current node (current->next = prev).
 Move prev to the current node (prev = current).
 Move current to the next node (current = next).

3. Return prev as the new head of the reversed list.

Implementation/Code:
#include <iostream>
using namespace std;

class Node {
public:
int value;
Node* link;

Node(int val) {
value = val;
link = nullptr;
}
};

Node* reverseList(Node* start) {


Node* previous = nullptr;
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
Node* current = start;
Node* following = nullptr;

while (current != nullptr) {


following = current->link; // Temporarily store next node
current->link = previous; // Reverse current node's pointer
previous = current; // Move previous to current node
current = following; // Advance current to next node
}

return previous; // New head of the reversed list


}

// Helper function to display the list


void displayList(Node* start) {
while (start != nullptr) {
cout << start->value << " ";
start = start->link;
}
cout << endl;
}

// Main function
int main() {
Node* start = new Node(1);
start->link = new Node(2);
start->link->link = new Node(3);
start->link->link->link = new Node(4);

cout << "Initial List: ";


displayList(start);

start = reverseList(start);

cout << "Reversed List: ";


displayList(start);

return 0;
}

Output:

Time Complexity: O(n×m)


Space Complexity: O(n)
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING

2. Problem 2: Postorder Traversal of a Binary Tree

Aim: To perform a postorder traversal of a binary tree.

Objective: Given the root of a binary tree, print the node values in postorder traversal (left,
right, root).

Algorithm:

 If the current node is NULL, return (base case).


 Recursively call postOrder() on the left subtree.
 Recursively call postOrder() on the right subtree.
 Print the value of the current node.

Implementation/Code:

#include <iostream>
using namespace std;

class TreeNode {
public:
int value;
TreeNode* leftChild;
TreeNode* rightChild;

// Constructor
TreeNode(int data) {
value = data;
leftChild = rightChild = nullptr;
}
};

// Post-order traversal function


void traversePostOrder(TreeNode* node) {
if (node == nullptr) return;

// Recursively traverse the left subtree


traversePostOrder(node->leftChild);

// Recursively traverse the right subtree


traversePostOrder(node->rightChild);

// Process the current node


cout << node->value << " ";
}
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
// Main function for post-order traversal
int main() {
// Creating a simple tree
TreeNode* rootNode = new TreeNode(1);
rootNode->leftChild = new TreeNode(2);
rootNode->rightChild = new TreeNode(3);
rootNode->leftChild->leftChild = new TreeNode(4);
rootNode->leftChild->rightChild = new TreeNode(5);

// Display post-order traversal


cout << "Post-order traversal: ";
traversePostOrder(rootNode);
cout << endl;

return 0;
}

Output:

Time Complexity: O(n)


Space Complexity: O(1)

3. Problem 3: Insert a Node into a Binary Search Tree (BST)

Aim: To insert a node into a binary search tree.

Objective: Given the root of a binary search tree and a value, insert the value into the
appropriate position in the BST.

Algorithm:

1. If the root is NULL, create a new node with the given value and return it.
2. Compare the value to be inserted with the current node's value:

 If the value is smaller, recursively insert it into the left subtree.


 If the value is larger, recursively insert it into the right subtree.

3. Return the root after insertion.

Implementation/Code:

#include <iostream>
using namespace std;
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
class TreeNode {
public:
int value;
TreeNode* leftChild;
TreeNode* rightChild;

// Constructor to initialize node with a value


TreeNode(int val) {
value = val;
leftChild = rightChild = nullptr;
}
};

// Function to insert a new value in the Binary Search Tree


TreeNode* addNode(TreeNode* root, int newValue) {
if (root == nullptr) {
return new TreeNode(newValue); // Create a new node if root is empty
}

if (newValue < root->value) {


root->leftChild = addNode(root->leftChild, newValue); // Insert in the left subtree
} else {
root->rightChild = addNode(root->rightChild, newValue); // Insert in the right subtree
}

return root; // Return the root node after insertion


}

// Inorder traversal for displaying the tree


void displayInOrder(TreeNode* root) {
if (root == nullptr) return;
displayInOrder(root->leftChild);
cout << root->value << " ";
displayInOrder(root->rightChild);
}

// Driver function to test the insertion into BST


int main() {
TreeNode* rootNode = new TreeNode(10); // Initial root node
rootNode = addNode(rootNode, 5);
rootNode = addNode(rootNode, 15);
rootNode = addNode(rootNode, 3);
rootNode = addNode(rootNode, 7);

cout << "Inorder traversal of BST: ";


displayInOrder(rootNode); // Display the tree in-order
cout << endl;
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING

return 0;
}

Output:

Time Complexity: O(nlog n)


Space Complexity: O(1)

4. Problem 4: Huffman Decoding

Aim: To decode a binary Huffman-encoded string using a Huffman tree.

Objective: Given the root of a Huffman tree and a binary-encoded string, decode the string
and return the original message.

Algorithm:

1. Start at the root of the Huffman tree.


2. For each character in the encoded string:
 If the character is '0', move to the left child of the current node.
 If the character is '1', move to the right child.
3. When a leaf node is reached, add the corresponding character to the decoded
message.
4. Continue from the root and repeat until the entire encoded string is processed.

Implementation/Code:
#include <iostream>
#include <string>
using namespace std;

class TreeNode {
public:
char character;
int frequency;
TreeNode* leftChild;
TreeNode* rightChild;

// Constructor to initialize the tree node with data and frequency


TreeNode(char ch, int freq) {
character = ch;
frequency = freq;
leftChild = rightChild = nullptr;
}
};
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING

// Function to decode a Huffman encoded string


void huffmanDecode(TreeNode* rootNode, const string& encodedStr) {
TreeNode* currentNode = rootNode;

// Loop through the encoded string


for (char bit : encodedStr) {
currentNode = (bit == '0') ? currentNode->leftChild : currentNode->rightChild;

// If a leaf node is reached, output the character


if (currentNode->leftChild == nullptr && currentNode->rightChild == nullptr) {
cout << currentNode->character;
currentNode = rootNode; // Reset to root for next character
}
}
}

// Main function to demonstrate Huffman decoding


int main() {
// Creating a sample Huffman Tree as per the example
TreeNode* rootNode = new TreeNode('\0', 0); // Root of the Huffman Tree
rootNode->leftChild = new TreeNode('A', 5); // Left child representing 'A' (0)
rootNode->rightChild = new TreeNode('\0', 6); // Right child subtree

// Further subdivision on the right side


rootNode->rightChild->leftChild = new TreeNode('R', 2); // 'R' (10)
rootNode->rightChild->rightChild = new TreeNode('\0', 4); // Subtree for 'B', 'C', 'D'
rootNode->rightChild->rightChild->leftChild = new TreeNode('B', 2); // 'B' (111)
rootNode->rightChild->rightChild->rightChild = new TreeNode('\0', 2); // Subtree for 'C',
'D'
rootNode->rightChild->rightChild->rightChild->leftChild = new TreeNode('C', 1); // 'C'
(1100)
rootNode->rightChild->rightChild->rightChild->rightChild = new TreeNode('D', 1); // 'D'
(1101)

// Encoded string to be decoded


string encodedMessage = "01111001100011010111100";

// Decode the encoded message using the Huffman Tree


cout << "Decoded Huffman string: ";
huffmanDecode(rootNode, encodedMessage);
cout << endl;

return 0;
}

Output:
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING

Time Complexity: O(nlog n)


Space Complexity: O(1)

5. Problem 5: Partitioning in Quicksort

Aim: To partition an array around a pivot element as part of the Quicksort algorithm.

Objective: Given an unsorted array and a pivot element (the first element), partition the
array into three parts:
 left (elements smaller than the pivot)
 equal (elements equal to the pivot)
 right (elements greater than the pivot).

Algorithm:

1. Initialize three empty arrays: left, equal, and right.


2. Set the first element of the array as the pivot.
 Traverse the array:
 If an element is smaller than the pivot, add it to left.
 If an element is equal to the pivot, add it to equal.
 If an element is greater than the pivot, add it to right.
3. Concatenate the three arrays (left + equal + right) and return the result.

Implementation/Code:
#include <iostream>
#include <vector>
using namespace std;

// Function to partition the array using the quick sort approach


vector<int> partitionArray(const vector<int>& inputArray) {
vector<int> leftPartition, pivotPartition, rightPartition;
int pivotElement = inputArray[0]; // Choose the first element as the pivot

// Loop through the array to partition elements


for (int element : inputArray) {
if (element < pivotElement) {
leftPartition.push_back(element); // Elements less than pivot
} else if (element == pivotElement) {
pivotPartition.push_back(element); // Elements equal to pivot
} else {
rightPartition.push_back(element); // Elements greater than pivot
}
}
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
// Merge the left, pivot, and right partitions
vector<int> finalArray;
finalArray.insert(finalArray.end(), leftPartition.begin(), leftPartition.end());
finalArray.insert(finalArray.end(), pivotPartition.begin(), pivotPartition.end());
finalArray.insert(finalArray.end(), rightPartition.begin(), rightPartition.end());

return finalArray;
}

// Driver function to test the partitioning of an array


int main() {
int arraySize;
cout << "Enter the number of elements in the array: ";
cin >> arraySize;

vector<int> inputArray(arraySize);
cout << "Enter " << arraySize << " space-separated integers: ";
for (int i = 0; i < arraySize; i++) {
cin >> inputArray[i];
}

// Partition the array


vector<int> partitionedArray = partitionArray(inputArray);

// Output the partitioned array


cout << "Partitioned array: ";
for (int num : partitionedArray) {
cout << num << " ";
}
cout << endl;

return 0;
}

Output:

Time Complexity: O(n×m×k)


Space Complexity: O(n×m)

6. Problem 6: Reverse a Linked List

Aim: Given the pointer to the head node of a linked list, change the next pointers of the
nodes so that their order is reversed. The head pointer given may be null meaning that the
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
initial list is empty.

Objective: Determine the number of ways to make a given amount using an unlimited
supply of different denominations of coins.

Algorithm:
1. Initialize a dp array of size amount + 1 with dp[0] = 1 (there is one way to make zero
amount).
2. Iterate over each coin in the given list of coins:
 For each coin, update the dp array for amounts from the coin value up to the target
amount.
 Add the number of ways to form the remaining amount (dp[i - coin]) to the current
amount dp[i].
3. Return dp[amount], which contains the total number of ways to form the given amount.

Implementation/Code:#include <iostream>
#include <vector>
using namespace std;

// Function to calculate the number of ways to make change for a given amount
long countChangeWays(int amount, const vector<int>& coinTypes) {
vector<long> ways(amount + 1, 0);
ways[0] = 1; // There's exactly one way to make change for 0 (using no coins)

// Loop through each coin denomination


for (int coin : coinTypes) {
for (int i = coin; i <= amount; i++) {
ways[i] += ways[i - coin]; // Add ways to make change by including the current coin
}
}
return ways[amount];
}

int main() {
int targetAmount, numOfCoins;

// Input the target amount and the number of different coin types
cout << "Enter the target amount and the number of coin denominations: ";
cin >> targetAmount >> numOfCoins;

vector<int> denominations(numOfCoins);

// Input the coin denominations


cout << "Enter the coin denominations: ";
for (int i = 0; i < numOfCoins; i++) {
cin >> denominations[i];
}
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING

// Output the number of ways to make change for the given amount
cout << "Number of ways to make change: " << countChangeWays(targetAmount,
denominations) << endl;

return 0;
}

Output:

Time Complexity: O(n)


Space Complexity: O(1)

7. Problem 7: Sum of Substrings

Aim: To compute the sum of all possible substrings of a given integer, represented as a
string.

Objective: Given a number as a string, find the sum of all substrings, modulo 109+710^9 +
7109+7.

Algorithm:

1. Initialize a variable totalSum = 0 to store the sum of all substrings.


2. For each digit in the string, calculate the contribution of the digit to every substring in
which it appears using positional notation.
3. Use dynamic programming to track cumulative sums.
4. The result will be the total sum modulo 109+710^9 + 7109+7.
Implementation/Code:
#include <iostream>
using namespace std;

const int MODULO = 1e9 + 7; // Constant to apply modulo operation

// Function to calculate the sum of all substrings of a given number string


int calculateSubstringSum(const string& numberStr) {
long long totalSum = 0;
long long multiplier = 1;
long long runningSum = 0;

// Iterate over the string from right to left


for (int i = numberStr.length() - 1; i >= 0; i--) {
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
runningSum = (runningSum + (numberStr[i] - '0') * multiplier) % MODULO;
totalSum = (totalSum + runningSum) % MODULO;
multiplier = (multiplier * 10 + 1) % MODULO;
}

return totalSum;
}

int main() {
string number;

// Input the number as a string


cout << "Enter the number: ";
cin >> number;

// Output the sum of all substrings


cout << "Sum of all substrings: " << calculateSubstringSum(number) << endl;

return 0;
}

Output:

Time Complexity: O(n)


Space Complexity: O(1)

8. Problem 8: Marc's Cupcake Walk

Aim: To calculate the minimum number of miles Marc needs to walk after eating cupcakes,
minimizing his calorie intake.

Objective: Given a list of cupcake calories, minimize the walking distance by eating higher-
calorie cupcakes first.

Algorithm:

1. Sort the cupcakes by calorie count in descending order.


2. For each cupcake, compute the walking distance as 2i×calories[i]2^i \times
\text{calories}[i]2i×calories[i], where i is the index of the cupcake.
3. Sum the distances and return the result.

Implementation/Code:
#include <iostream>
#include <vector>
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
#include <algorithm>
using namespace std;

// Function to calculate the minimum miles Marc needs to walk


long calculateMinMiles(const vector<int>& calorieValues) {
vector<int> sortedCalories = calorieValues;
sort(sortedCalories.begin(), sortedCalories.end(), greater<int>()); // Sort calories in
descending order
long totalMiles = 0;

// Calculate the total miles using the sorted calorie values


for (int i = 0; i < sortedCalories.size(); i++) {
totalMiles += (long) sortedCalories[i] * (1L << i); // Multiply by 2^i
}

return totalMiles;
}

int main() {
int cupcakeCount;

// Input the number of cupcakes


cout << "Enter the number of cupcakes: ";
cin >> cupcakeCount;

vector<int> calorieValues(cupcakeCount);

// Input the calorie values of the cupcakes


cout << "Enter the calorie values: ";
for (int i = 0; i < cupcakeCount; i++) {
cin >> calorieValues[i];
}

// Output the minimum miles Marc must walk


cout << "Minimum miles Marc must walk: " << calculateMinMiles(calorieValues) <<
endl;

return 0;
}

Output:
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
Time Complexity: O(n+m)
Space Complexity: O(1)

9. Problem 9: Shipping Containers

Aim: To determine the minimum number of containers required to ship items based on their
weights.

Objective: Group items such that each container can hold items whose weights differ by no
more than 4 units.

1. Sort the weights of the items.


2. Initialize a counter for containers.
3. For each item, group it with the next items whose weight difference is less than or
equal to 4.
4. Increment the container count for each new group.
Implementation/Code:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

// Function to calculate the minimum number of containers required


int calculateContainers(vector<int> weights) {
sort(weights.begin(), weights.end()); // Sort weights in ascending order
int containerCount = 0;

// Iterate through the sorted weights


for (int i = 0; i < weights.size(); i++) {
containerCount++; // Start a new container
int weightLimit = weights[i] + 4; // Set the limit for the current container

// Fill the current container with compatible weights


while (i < weights.size() && weights[i] <= weightLimit) {
i++;
}
i--; // Decrement to stay at the last item in the current container
}

return containerCount;
}

int main() {
int itemCount;

// Input the number of items


cout << "Enter the number of items: ";
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
cin >> itemCount;

vector<int> weights(itemCount);

// Input the weights of the items


cout << "Enter the item weights: ";
for (int i = 0; i < itemCount; i++) {
cin >> weights[i];
}

// Output the minimum number of containers required


cout << "Minimum number of containers required: " << calculateContainers(weights) <<
endl;

return 0;
}

Output:

Time Complexity: O(n)


Space Complexity: O(1)

10. Problem 10: Longest Common Substring with k Differences

Aim: To find the longest common substring of two strings that differ by no more than k
characters.

Objective: Given two strings, find the longest common substring that has at most k differing
characters.

Algorithm:
1. Use a sliding window approach to compare substrings.
2. For each possible substring pair, count the number of differing characters.
3. Maintain a record of the longest substring that satisfies the k-difference constraint.

Implementation/Code:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

int substringDiff(int k, string s1, string s2) {


DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
int maxLen = 0;
int len = s1.length();

// Sliding window comparison


for (int i = 0; i < len; i++) {
for (int j = 0; j < len; j++) {
int countDiff = 0;
int curLen = 0;

for (int l = 0; (i + l < len) && (j + l < len); l++) {


if (s1[i + l] != s2[j + l]) {
countDiff++;
}
if (countDiff > k) {
break;
}
curLen++;
}
maxLen = max(maxLen, curLen);
}
}

return maxLen;
}

int main() {
int t, k;
string s1, s2;
cout << "Enter the number of test cases: ";
cin >> t;

while (t--) {
cout << "Enter k and two strings: ";
cin >> k >> s1 >> s2;
cout << "Longest common substring length: " << substringDiff(k, s1, s2) << endl;
}

return 0;
}

Output:
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
Time Complexity: O(n)
Space Complexity: O(1)

Learning Outcomes:

i. Reverse a Linked List: Understand how to manipulate pointers in a linked list to reverse its
order effectively.

ii. Postorder Traversal of a Binary Tree: Learn to perform recursive traversals of binary trees
using postorder traversal technique.

iii. Insert a Node into a Binary Search Tree (BST): Gain insights into the properties of binary
search trees and how to maintain their structure during node insertion.

iv. Huffman Decoding: Understand how to decode a binary string using a Huffman tree by
traversing left for '0' and right for '1'.

v. Partitioning in Quicksort: Learn the partitioning process in quicksort, separating elements


based on a pivot to facilitate sorting.

vi. Count Change Ways: Master dynamic programming to calculate the number of ways to make
change for a specific amount using various coin denominations.

vii. Sum of Substrings: Explore techniques to compute the total sum of all possible substrings of a
number represented as a string efficiently.

viii. Marc's Cupcake Walk: Understand the strategy of sorting items to minimize costs in resource
allocation problems.

ix. Shipping Containers: Learn to group items based on weight constraints to optimize the use of
shipping containers.

x. Longest Common Substring with k Differences: Develop skills in string manipulation and
comparison to find the longest common substring under character difference constraints.

You might also like