Written Solutions - Computer Science

advertisement

Honors Computer Science I – Final Exam Solutions

Date: 4/26/11

1) (6 pts) Consider creating an array of size 100 of pointers to the type struct box. Create this declaration, and then allocate the memory for 100 struct box variables for each of those pointers to point to. No need to initialize any of the fields of each struct. Thus, there’s no need to know the composition of a struct box to finish this question. You may choose the name of your array. struct box* array[100]; // 2 pts int i; for (i=0; i<100; i++) // 1 pt

array[i] = malloc(sizeof(struct box)); // 3 pts

2) (4 pts) Write a segment of code to free the memory allocated in the previous question. Please use the same array name you chose in the previous question. int i; for (i=0; i<100; i++)

free(array[i]);

// 1 pt

// 3 pts

3) (4 pts) Give the values of each of the expressions below: a) 71 ^ 44

71 = 1000111

44 = 0101100

-----------

1101011 b) 123 | 78 c) 38 & 53 d) ~123

123 = 1111011

78 = 1001110

------------

1111111

38 = 100110

53 = 110101

----------------

100100 when x is positive,

Is –x–1.

As shown in class ~x,

107

127

36

-124

4) (5 pts) Convert 3FE

16

to both base 10 and base 2.

In decimal, we have 3x16 2 + 15 x 16 1 + 14 x 16 0 = 768 + 240 + 14 = 1022

In binary, we have 0011 1111 1110, converting each individual digit to binary.

3 pts for the process, 1 pt for each answer.

5) (5 pts) The function compute is defined below. What value does the function call compute(352921114) return? int compute(int n) {

if (n < 10)

return n;

return n%10*compute(n/10);

}

The function returns 3*5*2*9*2*1*1*1*4 = 2160.

4 pts for discovering that the digits of the number are multiplied, 1 pt for the answer.

6) (10 pts) Consider rewriting a recursive binary search so that instead of always searching exactly halfway in between the search boundaries, a random element is searched within the search boundaries. Everything else about the algorithm remains the same. (Namely, if the element examined is too small, we recursively search in the right side of the array, or if it’s too big, we recursively search in the left side of the array.) Write a function that implements this recursive search. The prototype is given for you below:

// Returns 1 if searchval is found in array[low…high], and 0

// otherwise. array is sorted in increasing order. int search(int array[], int low, int high, int searchval) { if (low > high) return 0; // 2 pts

int location = low + rand()%(high-low+1); // 3 pts

if(array[location] == searchval) // 1 pt

return 1; // 1 pt

else if (searchval > array[location]) // 1 pt

return search(array, location+1, high, searchval); //2pts

return search(array, low, location-1, searchval); // 2 pts

}

7) (5 pts) An algorithm runs in O(n k ) time, where k is a positive integer. With an input size of n =

100, the algorithm takes 15 milliseconds. With an input size of n = 500, the algorithm takes

1.875 seconds. What is the value of k?

Let the run-time of the algorithm be T(n) = cn k

.

We have T(100) = c(100) k = 15 and // 1 pt

T(500) = c (500) k = 1875 // 1 pt 𝒄𝟓𝟎𝟎 𝒌

𝟏𝟖𝟕𝟓

Divide the second equation by the first to yield 𝒄𝟏𝟎𝟎 𝒌

=

𝟏𝟓

𝟏𝟐𝟓 . (1 pt) Finally, this yields that 5 k = 125, so k = 3. (1 pt)

. (1 pt) Dividing, we get (

𝟓𝟎𝟎

𝟏𝟎𝟎

) 𝒌 =

8) (10 pts) The combination problem is very similar to the permutation problem: Given two integers, n and k, with n ≥ k, print out all distinct combinations of k integers from the set {1, 2, 3,

…, n}. For example, for n = 4 and k = 2, the following output is produced: (1,2), (1,3), (1,4), (2,

3), (2,4), and (3,4). Complete the function below so that it accomplishes this task. (You have four lines of code to complete, indicated by the underlines.) Note, the initial call to this function takes in an array inSubset[] that is initialized with all 0s, indicating false for each element. In particular, inSubset[k] stores 1 if k is in the current combination being formed and stores 0 if k is not in the current combination being formed. void combinations(int n, int r, int inSubset[], int length) {

if (r == 0) {

int i;

for (i=0; i<length; i++)

if (inSubset[i])

printf("%d ", i);

printf("\n");

}

else if (n < 0) {

return;

}

else {

inSubset[n] = 0; // 2 pts

combinations(n-1, r, inSubset, length); // 3 pts

inSubset[n] = 1; // 2 pts

combinations(n-1, r-1, inSubset, length); // 3 pts

}

}

9) (5 pts) What is the worst-case run-time of the following function in terms of the input parameter n? Please give your answer in terms of Big-Oh notation. In order to receive credit, your answer must be a tight upper bound. Thus, if O(n 2 ) is a valid answer, O(n 3 ) will not receive any credit, even if, technically, all algorithms that are O(n

2

) are also O(n

3

). Give a justification for your answer. int function(int array[], int n) {

int i;

while (i < 100) {

int guess = array[rand()%n];

if (guess%10 == 0)

return guess;

i++;

}

return 15;

}

This code never runs more than 100 iterations. All the work in each iteration takes constant time, thus the runtime of the function is constant, or O(1).

O(1) (3 pts for the answer, 2 pts for the explanation, no credit for any answers but O(1).)

10) (5 pts) Determine the value of the following sum: ∑ 99 𝑘=10

(4𝑘 − 7) .

The sum above is an arithmetic series with the first term 4(10) – 7 = 33, last term 4(99) – 7

= 389, with exactly 99 – 10 + 1 = 90 terms. Thus, the sum is

(𝟑𝟑+𝟑𝟖𝟗)

𝟐

× 𝟗𝟎 = 𝟏𝟖𝟗𝟗𝟎

Grading: Using this method, 1 pt for the 1 st term, 1 pt for last term. 1 pt for number of terms, 1 pt for the formula, 1 pt for the answer.

Using the summation notation, 1 pt for sum of k, 1 pt for pulling out constant 4, 1 pt for sum of constant, 1 pt for dealing with bounds, 1 pt for final answer

11) (10 pts) Show the final state of an AVL Tree after the following inserts have been made (in this order shown):

50, 30, 10, 20, 3, 14, 25, 40, 70, 43, 77

After 50, 30 and 10 are inserted, we do a rebalance to get 30

/ \

10 50

After 14 gets inserted we have 30

/ \

10 50

/ \

3 20

/

14

The imbalance is at the 30, so we get 20

/ \

10 30

/ \ \

3 14 50

After the 43 we have 20 , with imbalance at 30 20

/ \ / \

10 30 10 40

/ \ / \ / \ / \

3 14 25 50 3 14 30 50

/ \ / / \

40 70 25 43 70

\

43

After adding the 77 to the right of the 77, we get an imbalance at 20, so the final tree is 40

/ \

20 50

/ \ / \

10 30 43 70

/ \ / \

3 14 25 77

Grading: 1 pt off for each incorrect spot in the tree, cap at 0.

12) (10 pts) Write a function that takes a pointer to the root of a binary tree and returns the number of nodes in that tree that have exactly 1 child. The struct used for the binary tree and the function prototype are provided for you below. struct tree_node {

int data;

struct tree_node *left;

struct tree_node *right;

}; int numNodesWithOneChild(struct tree_node* root) { if (root == NULL) return 0; // 2 pts

int sum = 0;

if ((root->left == NULL && root->right != NULL) || // 2 pts

(root->left != NULL && root->right == NULL)) // 2 pts

sum = 1; // 1 pt

sum += numNodesWithOneChild(root->left); // 1 pt

sum += numNodesWithOneChild(root->right); // 1 pt return sum;

}

// 1 pt

13) (10 pts) Write a function that takes a pointer to the front of a linked list, rearranges the pointers so that the list is reversed (without allocating any new memory OR freeing any old member), and returns a pointer to the new front of the list. If the input parameter is NULL,

NULL should be returned. The struct and function prototype are provided below. Feel free to add extra functions. You may define the prototypes of those extra functions as you wish, but you can’t change the prototype already provided. struct node {

int data;

struct node *next;

}; struct node* reverse(struct node* front) {

if (front == NULL || front->next == NULL) // 1 pts

return front;

struct node* prev = front; // 1 pt

struct node* after = front->next;

prev->next = NULL; // 1 pt

while (after->next != NULL) { // 1 pt

struct node* third = after->next; // 1 pt

after->next = prev; // 1 pt

prev = after; // 1 pt

after = third; // 1 pt

}

after->next = prev;

return after;

}

// 1 pt

// 1 pt

14) (10 pts) In class we covered the Partition algorithm which is used in Quick Sort. Please fill in the code below so that the function partitions in the input array according to the algorithm.

// Pre-condition: low and high are valid indexes into values

// Post-condition: Returns the partition index such that all the values

// stored in vals from index low to until that index are

// less or equal to the value stored there and all the values

// after that index until index high are greater than that

// value. int partition(int* vals, int low, int high) {

int temp;

int i, lowpos;

i = low + rand()%(high-low+1);

swap(&vals[low], &vals[i]);

lowpos = low;

low++;

while (low <= high) {

while (low <= high && vals[low] <= vals[lowpos]) low++; // 3 pts

while (high >= low && vals[high] > vals[lowpos]) high--; // 3 pts

if (low < high) // 1 pt

swap(&vals[low], &vals[high]); // 3 pts

} swap(&vals[lowpos], &vals[high]); return high;

} void swap(int *a, int *b) {

int temp = *a;

*a = *b;

*b = temp;

}

15) (1 pt) After which hair product wearing real estate tycoon is Trump Towers named?

Donald Trump

Download