CSE 2320 Section 002, Fall 201 Exam 2 Time: 80 mins Name:. Student ID:. Total exam points: 100. Question Points Out of 1 24 2 10 3 10 4 18 6 1 16 Total 100 If you have the smallest doubt about what a question asks of you, or whether or not you can use certain code, ASK US! (Even if you think that it is a really silly question). All the answers need to be justified. No credit will be given if the answer is provided, but with no justification. 1
Question 1 24 points Consider this recursive function foo(n): int foo(int N){ if (N <= 1) return ; return foo(n-2) * foo(n-2); Use the function definition as is. There is no error. a) (3 points) Write the recurrence formula for this function. T(0) = 1 T(1) = 1 T(N) = 2 * T(N-2) + 1 b) (3 points) Solve the recurrence formula you gave above to compute the big- O complexity of this function. T(N) = 2 * T(N-2) + 1 = 2*[2*T(N-4) + 1] + 1 = 2 2 * T(N-2*2) + 2 + 1 = 2 2 *[2* T(N-3*2) + 1] + 2 + 1 = 2 3 * T(N-3*2) + 2 2 + 2 + 1. = 2 i * T(N-i*2) + 2 i-1 + + 2 2 + 2 + 1 = 2 N/2 * T(N-(N/2)*2) + 2 N/2-1 + + 2 2 + 2 + 1 = 2 N/2 * T(0) + 2 N/2-1 + + 2 2 + 2 + 1 = 2 N/2 + (2 N/2 1)/(2-1) = Θ(2 N/2 ) c) (6 points) Draw the tree that shows the function calls performed in order to compute foo() (the root will be foo() and it will have a child for each recursive call.) 3 3 3 3 1 1 1 1 1 1 1 1 2
d) (6 points) Use the tree to compute the number of function calls as a function of N (not the specific number of recursive function calls for foo(), but a formula that would give the number of calls for any N. SHOW YOUR WORK. (Continue on the next page if needed) Level i => 2 i nodes. Each node has a local cost of 1. Number of levels: L = N / 2 1, levels: 0,1,2, L-1 Number of nodes= number of recursive calls = 2 L-1 + 2 + 1 = = (2 L-1+1 1)/(2-1) = 2 L 1 (for the tree with 4 levels above, it gives 1 nodes) e) (6 points) Is it possible to re-implement this function so that it has running time O(N)? If not, why not? If yes, write this O(N) implementation of foo in C. Yes int foo(int N){ if (N <= 1) return ; int temp = foo(n-2) return temp * temp; Or with memoization. 3
Question 2 10 points (Tree. No code needed.) 0 14 8 11 4 3 20 2 a) (3 points) List the nodes in inorder: 14, 3,, 0, 20, 11, 2, 8, 4 b) (3 points) List the nodes in preorder: 0, 14,, 3, 8, 11, 20, 2, 4 c) (3 points) List the nodes in postorder: 3,, 14, 20, 2, 11, 4, 8, 0 4
Question 3 10 points (Quicksort. No code needed.) Given the array a = [3, 9, 2,, 10, 0, 6] show how quicksort sorts it. In the table below, print the elements of the array a between indexes left and r immediately before and after this line is executed: exch(a[i], a[r]) //line A: print before and after this Also circle the pivot. The quicksort code is provided below for your reference. void quicksort(item a[], int left, int r) { int i; if (r <= left) return; i = partition(a, left, r); quicksort(a, left, i-1); quicksort(a, i+1, r); int partition(item a[], int left, int r) { int i = left-1, j = r; Item v = a[r]; for (;;) { while (less(a[++i], v)) ; while (less(v, a[--j])) if (j == left) break; if (i >= j) break; exch(a[i], a[j]); exch(a[i], a[r]); //line A: print before and after this return i; When \index-> 0 1 2 3 4 6 Before quicksort starts: 3 9 2 10 0 6 Before: exch(a[i], a[r]); 3 0 2 10 9 6 After: exch(a[i], a[r]); 3 0 2 6 10 9 Before: exch(a[i], a[r]); 3 0 2 6 10 9 After: exch(a[i], a[r]); 3 0 2 6 10 9 Before: exch(a[i], a[r]); 0 3 2 6 10 9 After: exch(a[i], a[r]); 0 2 3 6 10 9 Call for l=0,r = 0,returns, no partition 0 2 3 6 10 9 Call for l=2,r = 2,returns, no partition 0 2 3 6 10 9 Before: exch(a[i], a[r]); 0 2 3 6 10 9 After: exch(a[i], a[r]); 0 2 3 6 9 10 Call for l=4,r = 4,returns, no partition 0 2 3 6 9 10 Call for l=6,r = 6,returns, no partition 0 2 3 6 9 10
Question 4 points (Stable algorithm?) Is quicksort stable? If your answer is yes, justify it (clearly explain or prove it). If your answer is no, give an example that shows it is not stable (give an array and show what the algorithm does that makes it not stable). Your answer should be with respect to the book s implementation of quicksort. (The code is provided in Question 3.) No. Counter example: 9 Jane Matt 10 Alice Mary Rick The pivot is. Quicksort will swap 9-Jane with -Mary and so -Mary is moved before -Matt. After partitioning the array will be: Mary Matt Rick 9 Jane 10 Alice 6
Question 18 points (Max Heap. No code needed.) a) (4 points) Is this a max-heap? Justify your answer. 20 18 3 1 No. There is a hole on the lowest level: node 18 does not have a right child. b) ( points) Delete the maximum element in the heap below. 40 30 20 30 2 16 2 6 3 16 10 3 Place 3 in the root and fixdown.
c) (9 points) Build a max heap by starting with an empty heap and inserting the following numbers in the given order. Show the heap after each insertion. N MAX heap after inserting the number N MAX heap after inserting the number 20 Heap after inserting 20: 20 60 60 / \ 0 40 / \ 1 20 40 Above heap after inserting 40 40 / 20 3 60 / \ 0 40 / \ / 1 20 3 0 Above heap after inserting 0 0 / \ 20 40 1 60 / \ 0 40 / \ / \ 1 20 3 1 So on 1 0 / \ 20 40 / 1 8
Question 6 1 points (Knapsack ) a) (6 points) Recover the items in the solution for Knapsack(49) given below. (The code is on the next page. The item indicates the item picked at that step.) ITEMS: Item A B C D E F Weight 2 3 8 10 Value 3 4 8 11 14 1 Bottom-up solution: Weight 0 1 2 3 4 6 8 9 Item A B A C A A E A Solution 0 0 3 4 6 8 9 11 14 14 Weight 10 11 12 13 14 1 16 1 18 19 Item A B A C A A E A A B Solution 1 18 20 22 23 2 28 28 31 32 Weight 20 21 22 23 24 2 26 2 28 29 Item A C A A E A A B A C Solution 34 36 3 39 42 42 4 46 48 0 Weight 30 31 32 33 34 3 36 3 38 39 Item A A E A A B A C A A Solution 1 3 6 6 9 60 62 64 6 6 Weight 40 41 42 43 44 4 46 4 48 49 Item E A A B A C A A E A Solution 0 0 3 4 6 8 9 81 84 84 A, Item[49-weight(A)]= Item[49-2]=Item[4] -> A, Item[4]->C, Item[4- weight(c)] = Item[4-]=Item[40]->E, The items: A, A, C, E, E, E, E, E, 9
b) (9 points) Using the same bottom-up algorithm, continue the computations for the solution below and compute the optimal value for weight 10 and fill out the Item and the Solution value in the table. You must show all the steps in computing the value. The code is provided below for your reference: int knapsack(int max_weight, struct Items items){ int * solutions = malloc(sizeof(int) * (max_weight + 1)); int weight, item; solutions[0] = 0; for (weight = 1; weight <= max_weight; weight++) { int max_value = 0; for (item = 0; item < items.number; item++) { int rem = weight - items.weights[item]; if (rem < 0) continue; int value = items.values[item] + solutions[rem]; if (value > max_value) { max_value = value; solutions[weight] = max_value; ITEMS: Item A B C D Weight 2 3 Value 3 4 8 12 Bottom-up solution: Weight 0 1 2 3 4 6 8 9 10 Item A B A C A D A A C Solution 0 0 3 4 6 8 9 12 12 1 16 Item Item value Item Weight Remaining weight: Solution of remaining weight Solution with this item A 3 2 10-2 = 8 12 12+3=1 B 4 3 10-3 = 12 12+4 = 16 C 8 10- = 8 8 + 8 = 16 D 12 10- = 3 4 4 +12 = 16 Pick any of the items that give value 16. I will pick B (this would be picked by the above code). 10
11
Question 16 points Trees write code a) (10 points) A binary tree structure is defined as follows: struct Tree { int item; struct Tree * left_child; struct Tree * right_child; Write a function int smallest_odd(struct Tree * tree1) that returns the smallest odd number stored in tree1. b) (3 points) Your code should not crash due to pointer errors. c) (3 points) What is the runtime of this function in terms of N, where N is the number of nodes in the tree. Justify your answer. Here I am giving one of the simplest solutions that would be accepted in an exam. If there are no odd numbers, I will return MAX_EVEN_INT (it is not odd so it indicates that no odd number was found). Note: if the largest even integer is smaller than the largest odd integer and the only odd values we have are the largest odd integer, this solution would return MAX_EVEN_INT instead of MAX_ODD_INT. int smallest_odd(struct Tree * tree1) { if (tree1 == NULL) return MAX_EVEN_INT; int curr_min = smallest_odd(tree1->left_child); int temp = smallest_odd(tree1->right_child); if (temp < curr_min) curr_min = temp; if ((tree1->item%2 == 1) && (tree1->item<curr_min)) curr_min = tree1->item. return curr_min; c) Θ(N) because each node is visited exactly once and the local cost is constant. Other solutions: 12
- Solution1: check if the returned value is also odd. It will not have the bug that the above solution has, but it is a bit more complicated. - Solution 2: use a tree traversal to copy the nodes in a list. Iterate over the list to find the smallest odd. Advantage: you will only have to compare only the item in the current node with the curr_min. 13