## CS302 Midterm, Fall, 2014

### Question 1: 14 points

• A: Straight from the lecture notes - O(m log(m)) - n. You get .20 points for l, m or o.
• B: Each deletion is O(log(n)) so this one is O(m log(n)). One point for m, .25 for l, n or o.
• C: Each Find() is O(α(n)) so this one is O(m α(n)). One point for i, .5 for j, .2 for h, k or f.
• D: Traversing the map is linear as is creating the vector: O(m) - f. You get 0.2 for g.
• E: Traversing the vector is linear, as is creating the heap: O(m) - f. You get 0.2 for g.
• F: Each Find() is O(log(n)) so this one is O(m log(n)). One point for m, .25 for l, n or o.
• G: There are exactly m! of these permuations: x You get .2 points for w.
• H: Each Pop() is O(log(n)) so this one is O(m log(n)). One point for m, .25 for l, n or o.
• I: This is like enumerating all m-digit numbers in base n: s. You get .5 points for u.
• J: This is O(m log(m)), but if you put O(m2), I gave you full credit. (n and r).
• K: Each Push() is O(log(n)) so this one is O(m log(n)). One point for m, .25 for l, n or o.
• L: Straight from the lecture notes - O(m2) - r. You get .25 points for q.
• M: O(m log(m)), plain and simple - n. You get .20 points for l, m or o.
• N: Each Union() is O(1)), so this is O(m)) - f. You get .20 points for i or j.

This is an interesting example of crowd-sourcing: The class majority got 100%:

 a b c d e f g h i j k l m n o p q r s t u v w x y z A 1 0 0 0 6 0 0 0 0 0 0 4 2 56 3 0 0 2 0 0 0 0 0 0 0 0 B 0 0 0 7 2 4 0 0 0 0 0 3 54 2 0 2 0 0 0 0 0 0 0 0 0 0 C 0 2 5 1 1 1 1 0 44 1 1 0 14 2 1 1 0 0 0 0 0 0 0 0 0 0 D 1 0 1 1 2 37 4 0 0 0 0 2 18 3 0 3 2 1 0 0 0 0 0 0 0 0 E 0 1 0 0 4 48 8 0 0 0 0 0 3 8 0 3 0 0 0 0 0 0 0 0 0 0 F 0 0 1 1 0 3 0 0 3 0 0 1 60 2 1 3 0 0 0 0 0 0 0 0 0 0 G 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 2 1 6 7 9 1 0 1 37 8 0 H 0 0 0 8 1 3 0 0 1 0 0 1 58 1 0 2 0 0 0 0 0 0 0 0 0 0 I 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 2 1 37 23 0 0 3 1 4 1 J 0 1 0 0 12 3 0 0 0 0 0 0 3 54 1 0 0 1 0 0 0 0 0 0 0 0 K 0 0 0 5 1 3 1 0 1 0 2 1 59 1 1 0 0 0 0 0 0 0 0 0 0 0 L 0 0 0 0 2 4 0 0 0 0 1 5 0 2 1 0 3 57 0 0 0 0 0 0 0 0 M 0 1 0 0 11 13 0 0 0 0 0 4 8 30 1 5 1 1 0 0 0 0 0 0 0 0 N 24 0 0 0 0 41 0 0 4 0 0 0 3 1 0 1 0 0 1 0 0 0 0 0 0 0

### Question 2: 17 points

• A - D: Each of these returns the root of the set: 6, 10, 10 and 4. 1 point each.
• E: The set rooted by 10 is bigger, so 10 becomes the parent of 6:

Grading. I just went multiple choice on this, with the entries for 4, 6 and 10 counting 1 point each, and the remainder (including the empty 22) counting 0.2 points each.

• F: The set rooted by 6 is higher, so 6 becomes the parent of 10:

Grading: .5 point for 10's link being 6, .5 point for 6's link being -1, and 1 point for all of the others being identical to part E.

• G: The links for 12 and 0 both change to 6. 1 point for 12, 1 point for 0, 1 point for not saying anything else.

### Question 3: 15 points

• Bubble: With bubble sort, you'll keep swapping 186 until you reach 192. Then you keep swapping 192 until you reach 198. You swap 198 with 131, and you're done:
```121  73  79 186 138  16  68 192 131 198
```
So, the answer is v. One point for w.

• Selection: You will swap 16 and 186, and 68 and 121:
``` 16  68  73  79 192 138 186 121 198 131
```
So, the answer is b. One point for l. One point for f.

• Insertion: To sentinelize, you first swap 16 and 186. The vector will be as in answer l. Then, after two passes, the first four elements will be sorted. Think about that. After sentinelizing, the lowest element is at index 0. On the first pass of sorting, you'll start with index 2, because the element at index 1 is already "sorted:"
``` 16  73  79 121 192 138 186  68 198 131
```
So, the answer is g. If you started with index 1 rather than 2, then you would get h, so I gave that full credit too. If you didn't sentinelize, then you'd get either s or t, so I gave half credit for either of those answers.

• Merge: When the first recursive call is done, the first 5 elements will be sorted, and the last 5 elements will be unchanged:
``` 73  79 121 186 192 138  16  68 198 131
```
So, the answer is r. Half credit for q, as that's what it looks like after the second recursive call (just before the merge).

• Bucket: I gave you a 20-element vector on your scratch sheet for you to fill out. Since the elements are assumed to be uniformly distributed between 0 and 200, you can simply chop off their last digits to see where they should go in the 20-element vector. If an element is already there, you look lower, then higher, one slot at a time, until you find an empty slot. Here's what it should look like when you're done:

When you condense that into one 10-element vector, you get:

``` 16  68  79  73 121 138 131 198 186 192
```
So, the answer is d. Half credit for e. One point for a.

 a b c d e f g h i j k l m n o p q r s t u v w x y z A 0 0 0 0 0 0 0 0 0 0 0 2 3 0 0 0 0 0 0 0 0 54 3 2 11 0 B 0 58 0 0 0 9 0 1 1 0 0 1 0 0 0 0 0 2 2 1 0 0 0 0 0 0 C 2 3 2 0 1 12 18 12 4 0 0 3 1 0 0 0 1 1 11 3 0 0 0 0 0 1 D 1 1 0 0 0 0 0 0 0 1 1 1 0 2 3 2 18 29 1 1 0 0 0 4 7 1 E 19 0 3 11 5 1 3 0 0 8 4 0 2 4 3 0 2 1 0 1 0 0 0 1 0 2

### Question 4: 14 points

Push the value to the end of h and percolate up:

 ```void PQueue::Push(double d) { int index, p; h.push_back(d); index = h.size()-1; while (1) { if (index == 0) return; p = (index - 1) / 2; if (h[p] <= h[index]) return; h[index] = h[p]; h[p] = d; index = p; } } ```

• Correct syntax on the first line of the implementation: 2 points.
• h.push_back(d): 2 points
• Exiting at the root: 2 points
• Calculating the parent correctly: 2 points
• Exiting when the parent is less than the child: 2 points
• Swapping otherwise and setting child to parent: 2 poitns
• Nothing extraneous: 2 points

### Question 5: 19 points

Outline your solution in English: This is going to be a power set enumeration. I want to enumerate all subsets of N. Each subset that I enumerate will represent the number of red balls, and the elements not in the subset will represent the number of blue balls. I'll calculate those values, and if they equal r and b, then I return 1. If I reach the end of the enumeration without finding r and b, I'll return 0. It would save some time were I to total up the elements of N and making sure that it equals r+b before bothering with the enumeration. You didn't have to do that.

With 20 elements which can each be 199,999,999, these sums can exceed the maximum value of an integer. For that reason, your sums should be long long's, rather than integers.

N's size: A power set enumeration of N elements is O(2N). You start reaching the 2 second limit in Topcoder at about 222.

Here's an implementation with a main(): (in q5.cpp)

 ```#include #include #include #include using namespace std; int RB(int r, int b, vector &N) { long long R, B; int i, j; R = 0; for (i = 0; i < N.size(); i++) R += N[i]; if (R != r + b) return 0; for (i = 0; i < (1 << N.size()); i++) { R = 0; B = 0; for (j = 0; j < N.size(); j++) { if (i & (1 << j)) { R += N[j]; } else { B += N[j]; } } if (R == r && B == b) return 1; } return 0; } main() { int r, b, i; vector N; cin >> r >> b; while (cin >> i) N.push_back(i); printf("%d\n", RB(r, b, N)); exit(0); } ```

• Answer in English: 5 points
• Constraints: 3 points
• Performing the correct outer loop: 2 points
• Performing the correct inner loop: 2 points
• Calculating R and B: 2 points
• Returning 1 when you find r and b: 2 points
• Using long long for R and B: 2 points
• Returning 0 when you don't find r and b: 1 point