CSCI 3333 Midterm
Accessing an element of the vector (via operator[ ])
O (1) O ( n )
Adding an element to the back of the vector (via push_back)
O (1) O ( n )
Inserting a new element before the lement at the specified position vector (via insert)
O (1) O ( n )
Removing an element from the front of the vector (via erase)
O (1) O ( n )
Below is an input array from the universe U = {0 , 1 , . . . , 999 }. The for-loop in radix sort with | D| = 10 , | U| = 1000 iterates log | D | | U| = 3 times. 329-442-917-640-287-194-385-874-500-499 Fill in the array after the first iteration of radix sort: 640-... Second array of radix sort:... Third array of radix sort:...
..
Below is an input array from the universe of length-4 lowercase alphabetic strings. The for-loop in radix sort with | D| = 26 , | U| = 26 4 iterates log | D | | U| = 4 times. abcd-zydq-booo-zoom-exam-tree-smol-code-cats-skis Fill in the first, second, third and fourth array of radix sort.
..
Below is an input array of ints from the universe U = { 1, 2, 3, 4, 5 } 3-4-2-1-4-5-3-1-2-4 Fill in the histogram computed by countin sort based on the array above: 1 - 2 - 3 - 4 - 5
..
Complete the following function that prints the elements of the Nodes visited during a search for s. The elements should be printed in reverse order of their visit (i.e., the root should be printed last). void visited(Node* root, string s) { if (root == nullptr) return; if (root->x == s) { cout << root->x << endl; return; } if (root->x < s) visited(root->_____, s); else visited(root->_____, s); cout << _____ << endl; }
..
Complete the following function that replaces each element of a vector V with three copies of the element: void duplicate(vector<_____> &V) { vector<string> C = V; V.clear(); while (C.size() > 0) { V.push_back(C[_____]); V.push_back(C[_____]); V.push_back(C[_____]); C.erase(C.begin()); } } For instance, the following tests should pass: vector<string> V{"dog", "cat", "bird"}; duplicate(V); test(V.size() == 6); test(V[0] == "dog"); test(V[1] == "dog"); test(V[2] == "dog"); test(V[3] == "cat"); test(V[4] == "cat"); test(V[5] == "cat"); test(V[6] == "bird"); test(V[7] == "bird"); test(V[8] == "bird"); Let n be the length of V. The running time of duplicate is: O (1) O ( n ) O ( n 2 )
..
Complete the following function that replaces every element of a vector V with the sum of the elements of V: void replace_with_sum(vector<int> _____V) { if (V.size() == _____) return; int sum = 0; for (int x : _____) sum += x; for (int i = 0; i < V._____(); ++i) V[i] = _____; } For instance, the following tests should pass: vector<int> V{2, 1, 3}; replace_with_sum(V); test(V.size() == 3); test(V[0] == 6); test(V[1] == 6); test(V[2] == 6); Let n be the length of V. The running time of replace_with_sum is: O (1) O ( n ) O ( n 2 )
..
Complete the following implementation of a C++ function that returns whether an array A of length n contains a positive number. bool contains_positive(int* A, int n) { for (int i = 0; i < _____; ++i) if (A[i] _____ 0) return _____; return _____; }
..
Complete the following implementation of a C++ function that returns whether the sum of the elements of an array A is larger than a given integer k. bool positive_sum(int* A, int n, int k) { int tot = 0; for (int j = 0; j < _____; ++j) tot _____ A[j]; return (tot _____ k); }
..
Complete the following implementation of a C++ function that returns whether two arrays A and B, both of length n, are equal (i.e. contain the same sequence of elements). bool equal(int* A, int* B, int n) { for (int i = 0; i < n; ++i) if (A[i] _____ B[_____]) return _____; return _____; }
..
Complete the following implementation of a function that performs a left rotation on the AVL tree rooted at root. void left_rotate(Node* root) { Node* rc = root->right; root->_____ = rc->right; rc->right = _____; rc->left = _____; root->left = _____; swap(root->x, rc->x); update_lrot_heights(root); }
..
Complete the following implementation of counting sort for the universe of chars. void sort(char* A, int n) { int H[ _____ ]; for (int k = 0; k < _____; ++k) H[k] = _____; for (int k = 0; k < n; ++k) H[A[k]] += _____; int k = 0; int i = 0; while (i < _____ ) { if (H[i] == _____) ++i; else { A[k] = _____; ++k; H[i] = H[i] _____ 1; } } }
..
Complete the following implementation of the function update_lrot_heights from Problem 3 (and helper function update_node_height that updates the heights of nodes after performing a left rotation. void update_node_height(Node* cur) { if (cur->left != nullptr && cur->left->height > cur->height) cur->height = _____; if (cur->right != nullptr _____ cur->right->height > _____) cur->height = _____; } void update_lrot_heights(Node* root) { update_node_height(root->_____); update_node_height(root); }
..
Complete the following template function that fills a vector with the contents of a BST in sorted order. template <typename T> void fill_sorted(vector<T> &V, Node<T>* root) { if (root == nullptr) return; fill_sorted(_____, root->_____); V.push_back(root->x); fill_sorted(_____, root->_____); }
..
Complete the following template function that prints only the internal nodes of a BST. template <typename T> void print_internal_nodes(Node<T>* root) { if (root == nullptr) _____; if (root->left _____ _____) cout << root->x << endl; else if (root->right _____ _____) cout << root->x << endl; print_internal_nodes(root->left); print_internal_nodes(root->right); } For trees with n nodes, the running time of print_internal_nodes is O(*function of n and h*).
..
Complete the following template function that returns the number of elements larger than x in the BST rooted at root. template <typename T> int after(T x, Node<T>* root) { if (root->x < x) return after(x, root->_____); int lc = after(_____, root->left); int rc = after(_____, root->right); if (root->x _____ x) return lc + rc + _____; return lc + rc; }
..
Determine the truth of the following statements about AVL trees. Every AVL tree is balanced. Every AVL tree is complete. Some AVL trees are complete. The minimum number of rotations done in an AVL tree insert is 1 For each statement: True False
..
Determine the truth of the following statements about BSTs with n nodes and height h. The worst-case running time of searching is O(n + h). The running time of printing all elements is O(n). The worst-case running time of insertion is O(log(n)) |_ log2(n) _| ≤ h ≤ n For each statement: True False
..
Determine the truth of the following statements about binary search trees with n nodes. The node containing the median value is always the root. The node containing the largest value is never a leaf. If the root has no right child, then it contains the largest value. The maximum height of such a tree is n − 1. For each statement: True False
..
Determine the truth of the following statements about counting sort for a universe U. The worst-case running time of counting sort is O (n + | U | ). The best-case running time of counting sort is O (n ). Counting sort can sort floats and strings. Counting sort can sort negative integers. For each statement: True False
..
Determine whether sorting algorithms with the following worst-case, average-case, and best-case running times can exist. Worst-case: O( n log( n)) Average-case: O( n log( n)) Best-case: O( n) Worst-case: O( n 2) Average-case: O( n 2) Best-case: O( n) Worst-case: O( n 2) Average-case: O( n log( n)) Best-case: O( n 2) Worst-case: O( n) Average-case: O( n) Best-case: O( n) For each set: Yes No
..
Fil in the blanks with answers based on the AVL tree in Figure 2. 10 4 15 2 12 16 20 If insert(1) was called, *number* rotations would occur during the call. If insert(1) was called, the left child of *number* would change to *number* during the first rotation. If erase(12) was called, *number* rotations would occur during the call. If erase(12) was called, the left child of *number* would change to *number* during the first rotation.
..
Fill in the blanks below to perform asymptotic analysis of the worst-case running time of the following function that searches in an unsorted array: bool search(int x, int* A, int n) { if (n < 1) return false; if (A[0] == x) return true; return search(x, &(A[1]), n-1); } The recurrence relation f(n) = _____*function of f(n-1)*_____ with f(0) = O(_____*function of n*_____) describes the worst-case running time of _search_ Using repeated substitution once on the recurrence relation gives f(n) = _____*function of f(n-2)*_____. A closed form of the worse-case running time of _search_ is f(n) = O(_____*function of n*_____)
..
Fill in the blanks regarding the worst-case running times for the following algorithms and functions on a binary search tree with n nodes and height h. • The running time of insertion is O(*function of n and h*). • The running time of function max in Problem 1 of pqTREE1 is O(*function of n and h*). • The running time of function after in Problem 2 of pqTREE1 is O(*function of n and h*). • The running time of function fill_sorted in Problem 3 of pqTREE1 is O(*function of n and h*).
..
Fill in the blanks with answers about tries. The trie containing strings "a" , "ab" , and "abc" has *number* nodes. There are at most *number* binary strings in a trie of height 2. The maximum number of strings in a trie containing 10 nodes is *number*. The minimum number of strings in a trie containing 10 nodes is *number* .
..
Fill in the blanks with answers based on AVL trees. f ( h ) = *function of f(h −1),f(h −2),...* with f (0) = *number*, f (1) = *number* is the recurrence relation describing the minimum number of nodes in an AVL tree of height h. The minimum number of nodes in an AVL tree of height 3 is *number* . The maximum number of nodes in an AVL tree of height 3 is *number* . The minimum number of nodes in an AVL tree of height 4 is *number*
..
Fill in the blanks with answers based on the AVL tree in Figure 1. 10 4 15 2 12 16 20 If insert(3) was called, *number* rotations would occur during the call. If insert(3) was called, the left child of *number* would change to *number* during the first rotation. Calling insert(*number*) , then insert(*number*) causes 0 total rotations. Calling erase(*number*) causes 15 to become the root of the tree.
..
Fill in the blanks with answers based on the trie in Figure 2. Figure 2: There are *number* strings in the trie and the longest string in the trie is *string*. Inserting *string* would cause no new nodes to be created. Erasing *string* from the trie would cause 2 nodes to be erased.
..
In Figure 1, complete the marking of nodes for a trie that contains the strings "acac" , "acc" , "bb" , "cab" , "ccaa" , "cc" , "ccc" , and "" . Figure 1: acac, acc, bb*(marked), cab, ccaa, ccc
..
Select the worst-case running time for insertion sort limited to the following sets of input arrays. ~Sorted arrays. E.g., {2, 4, 6, 8, 10, 12, 14}. O( n) O( n 2) ~Reverse sorted arrays. E.g., {13, 11, 9, 7, 5, 3, 1}. O( n) O( n 2) ~Up-down arrays. E.g., {2, 4, 6, 8, 7, 5, 3}. O( n) O( n 2) ~Alternating arrays. E.g., {1, 6, 4, 5, 2, 8, 3}. O( n) O( n 2) Here are definitions for each set of arrays. Assume the length of the array is n. ~_Sorted array_: for every pair of indices i , j , if i < j , then A[i] < A[j] . ~_Reverse sorted array_: for every pair of indices i , j , if i < j , then A[i] > A[j] . ~_Up-down array_: there exists an index k such that the portion of the array from index 0 to index k is a sorted array and the portion of the array from index k to index n-1 is a reverse sorted array. ~_Alternating array_: for every index i , A[i] < A[i+1] && A[i+1] > A[i+2] or A[i] > A[i+1] && A[i+1] < A[i+2] .
..
bool conditional(int* D, int n) O (1) O ( n ) O ( n ) { for (int i = 0; i < n; ++i) { if (D[i] == n/3) return true; } return true; } O (1) O ( n ) O ( n 2 )
..
bool search(int x, int* A, int n) { if (linear_search(x, A, n)) return true; insertion_sort(A, n); return binary_search(x, A, n); } O( n) O( n log( n)) O( n2)
..
bool search(int x, int* A, int n) { quicksort(A, n); return binary_search(x, A, n); } O( n) O( n log( n)) O( n 2)
..
bool search_n_sort(int* A, int n) { for (int x = 1; x <= n; ++x) if (linear_search(x, A, n)) return true; insertion_sort(A, n); return false; } O( n) O( n log( n)) O( n2)
..
bool sort_n_search(int* A, int n) { insertion_sort(A, n); for (int x = 1; x <= n; ++x) if (binary_search(x, A, n)) return true; return false; } O( n) O( n log( n)) O( n2)
..
int first_third_sum(float* A, int n) { int tot = 0; for (int i = 0; i < n/4; ++i) tot += A[i]; return tot; } O (1) O ( n ) O ( n 2 )
..
int return_when_small(int* C, int n) O (1) O ( n ) O ( n 2 ) { int tot = 3; if (n < 50) return tot; for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j) tot -= C[i] * (2 * C[j]); return tot; } O (1) O ( n ) O ( n 2 )
..
int sum_a_hundred_times(int* B, int n) { int tot = 0; for (int i = 0; i < 50; ++i) for (int j = 0; j < n; ++j) tot += B[j]; return tot; } O (1) O ( n ) O ( n 2 )
..
int sum_array_alt(int* D, int n) { int s = 0; for (int i = 0; i < n; ++i) { s += D[i]; ++i; } return s; } O (1) O ( n ) O ( n 2 )
..
int sum_array_start(int* C, int n) { int s = 0; for (int i = 0; i < 100; i=i+2) s += C[i]; return s; } O (1) O ( n ) O ( n 2 )
..
n! >> 2^n >> n^2 >> n >> nlog n >> n >> logn >> 1
..
void all_the_sorting(int* A, int n) { insertionsort(A, n); mergesort(A, n); quicksort(A, n); } O( n) O( n log( n)) O( n 2)
..
void sort_again(int x, int* A, int n) { insertion_sort(A, n); if (binary_search(x, A, n)) merge_sort(A, n); } O( n) O( n log( n)) O( n 2)
..
void sort_again(int x, int* A, int n) { insertionsort(A, n); if (binary_search(x, A, n)) mergesort(A, n); } O( n) O( n log( n)) O( n 2)
..
void sort_again2(int x, int* A, int n) { mergesort(A, n); if (binary_search(x, A, n)) return true; else insertion_sort(A, n); return false; } O( n) O( n log( n)) O( n 2)
..
void sum_array(int* A, int n) { int s = 0; for (int i = 0; i < n/2; ++i) s += A[i]; } O (1) O ( n ) O ( n 2 )
..
void sum_array_pairs(int* B, int n) { int s = 0; for (int i = (n mod 2); i < n; ++i) for (int j = 0; j < n; ++j) s += (B[i] + B[j]); } O (1) O ( n ) O ( n 2 )
..
void very_sort(int* A, int n) { for (int i = 0; i < n; ++i) insertionsort(A, n); } O( n) O( n log( n)) O( n2)
..
Complete the following template function that returns the largest element of the BST rooted at root. template <typename T> T max(Node<T>* root) { if (_____ _____ nullptr) return T(); if (root->right == _____) return root->x; return max(root->_____); }
...
Binary Search Tree
Insert, Search, Delete: O(logn) Worse: O(n)
Radix Sort
O(n) for worst, best average
Counting Sort
O(n+k) for worst, average, best
AVL Tree
Search time: O(logn) insert time: O(logn) worst case time:
Merge sort
Theta(nlogn) for worst, best, average Divides array in two halves and takes constant time to merge
Binary Search
Worse case: Theta(log n) Best case: Theta(1)
Quick sort
Worst Case : O(n^2) Best Case : O (n log n) Average Case : O (n log n)
Insertion Sort
Worst Case : O(n^2) Best Case : Ω(n) Average Case : Θ(n^2)
Linear Search
worst case: Theta(n) best case: Theta(1)