Q1) Linked Lists (15 points)
ListNode *mergeListsAndReverse(ListNode *listA, ListNode *listB) {
ListNode *reversed = nullptr;
ListNode *tmp;
// traverse both lists and compare ListNodes
// don't stop until both lists are nullptr
while (listA != nullptr || listB != nullptr) {
// only check data if listA is not nullptr
if (listA != nullptr && (listB == nullptr || listA->data < listB->data)) {
// rewire listA
tmp = listA->next;
listA->next = reversed;
reversed = listA;
listA = tmp;
} else {
// rewire listB
tmp = listB->next;
listB->next = reversed;
reversed = listB;
listB = tmp;
}
}
return reversed;
}
Q2) Binary Search Trees (25 Points)
// bst.h
// Did not modify BST_Node
struct BST_Node {
int data;
BST_Node *left;
BST_Node *right;
};
class BST {
// Did not modify public class members
public:
BST(); // constructor
~BST(); // destructor
// insert value into BST, ignoring duplicates
void insert(int value);
// removes all nodes less than min and greater than max
void removeOutOfRangeNodes(int min, int max);
// prints the in-order representation of the tree
// in the following form:
// 1,2,3,4
// with an endl after the list of values.
void printTreeInOrder();
private:
BST_Node *root;
// helper function for insert
void insertHelper(BST_Node *&n, int value);
// cleans up the BST
void deleteTree(BST_Node *n);
// add more private functions if needed
BST_Node *removeOutOfRangeNodesHelper(BST_Node *current, int min, int max);
void printTreeInOrderHelper(BST_Node *n, int lefts);
};
// bst.cpp
BST::BST() {
root = nullptr;
}
BST::~BST() {
deleteTree(root);
}
void BST::insert(int value) {
insertHelper(root,value);
}
// helper function for insert
void BST::insertHelper(BST_Node *&n, int value) {
if (n == nullptr) {
n = new BST_Node;
n->data = value;
n->left = nullptr;
n->right = nullptr;
} else {
if (value < n->data) {
insertHelper(n->left, value);
} else if (value > n->data) {
insertHelper(n->right, value);
}
}
}
void BST::removeOutOfRangeNodes(int min, int max) {
root = removeOutOfRangeNodesHelper(root, min, max);
}
BST_Node *BST::removeOutOfRangeNodesHelper(BST_Node *current, int min, int max) {
if (current == nullptr) {
return nullptr;
}
current->left = removeOutOfRangeNodesHelper(current->left, min, max);
current->right = removeOutOfRangeNodesHelper(current->right, min, max);
if (current->data < min) {
BST_Node *temp = current->right;
delete current;
return temp;
}
if (current->data > max) {
BST_Node *temp = current->left;
delete current;
return temp;
}
return current;
}
void BST::printTreeInOrder() {
printTreeInOrderHelper(root,0);
}
void BST::printTreeInOrderHelper(BST_Node *n, int lefts) {
if (n == nullptr) return;
printTreeInOrderHelper(n->left, lefts+1);
cout << n->data;
if ((lefts == 0 && n->right == nullptr)) {
// we are at the max node
cout << endl;
} else {
cout << ", ";
}
printTreeInOrderHelper(n->right, lefts);
}
void BST::deleteTree(BST_Node *n) {
if (n != nullptr) {
// post-order traversal
deleteTree(n->left);
deleteTree(n->right);
delete n;
}
}
Q3) Recursion - Wildcard Matches (15 Points)
bool filenameMatches(string filename, string pattern) {
if (pattern == "") return (filename == "");
int n = filename.length();
switch (pattern[0]) {
case '?':
if (filename == "") return false;
return filenameMatches(filename.substr(1), pattern.substr(1));
case '*':
for (int i = 0; i <= n; i++) {
if (filenameMatches(filename.substr(i), pattern.substr(1))) {
return true;
}
}
return false;
default:
if (filename == "" || pattern[0] != filename[0]) return false;
return filenameMatches(filename.substr(1), pattern.substr(1));
}
}
Q4) Break Sentence into Dictionary Words (15 Points)
void breakSentenceHelper(Lexicon &lex, string str, int n, string result) {
// look at all potential prefixes
for (int i=0; i < n; i++) {
// get the prefix
string prefix = str.substr(0, i+1);
// if the lexicon contains the prefix, use it,
// and check the rest of the string;
// otherwise, we ignore it
if (lex.contains(prefix)) {
// if we're at the end of the string, print
if (i == n-1) {
result += prefix;
cout << result << endl;
} else {
breakSentenceHelper(lex, str.substr(i+1, n-i-1), n-i-1,
result + prefix + " ");
}
}
}
}
void breakSentence(Lexicon &lex, string str) {
breakSentenceHelper(lex, str, str.size(), "");
};
Q5) Hash Map (15 Points)
0: 20, your -> 40, hash
1:
2:
3:
4:
5:
6: 6, map
7: 87, skills -> 27, are
8: 88, fantastic -> 28, and
9: 29, you
10:
11: 51, will
12:
13: 53, get -> 13, full
14:
15:
16:
17:
18: 78, credit
19:
Final number of elements: 12
Capacity: 20
Load factor: 12/20 = 0.6 (or 3/5)
Q6) Backtracking: All Paths from Start to Finish (15 points)
Vector<string> allPaths(Grid<bool> &g) {
return allPathsHelper(g, 0, 0, "");
}
Vector<string> allPathsHelper(Grid<bool> &g, int r, int c, string path) {
Vector<string> paths;
if (!g.inBounds(r,c) or g[r][c]) {
// already visited, or out of bounds
return paths;
}
if (r == g.numRows() - 1 and c == g.numCols() - 1) {
// we've reached the end
paths.add(path);
return paths;
}
// general idea: mark current position as visited,
// then visit all neighbors
g[r][c] = true; // visited
paths += allPathsHelper(g, r-1, c, path + "n");
paths += allPathsHelper(g, r, c+1, path + "e");
paths += allPathsHelper(g, r+1, c, path + "s");
paths += allPathsHelper(g, r, c-1, path + "w");
// unmark
g[r][c] = false;
return paths;
}