数据结构算法代写: CS112 COMPUTER SCIENCE 112

9/17/2016 CS112 Fall 2016: Problem Set 1

Problem Set 1 Big O

1. Exercise 3.7 of the textbook.

An algorithm prints the following pattern:

*
** *** **** *****

  1. What are the basic operations performed by the algorithm that you would count towards its running time?
  2. Count the number of these basic operations for the specific output shown above.
  3. The number of lines printed in the preceding pattern is 5. Assume that the algorithm can extend this

    pattern for any number of lines (line number i has i stars). If the number of lines, n is the input to

    the algorithm, how many basic operations are performed as a function of n?

  4. Write your answer to the above question as a big O order.

SOLUTION

a. Printing a star, printing a blank space, printing a newline
b. 15 print stars, 10 print blank spaces, 5 print newlines
c. n*(n+1)/2 print stars, n*(n‐1)/2 print spaces, n print newlines

d. O(n2)
2. Exercise E3.10, page 117 of the textbook.

A spreadsheet keeps track of student scores on all the exams in a course. Each row of the spreadsheet corresponds to one student, and each column in a row corresponds to his/her score on one of the exams. There are r students and c exams, so the spreadsheet has r rows and c columns.

Consider an algorithm that computes the total score on all exams for each student, and the average class score on each exam. You need to analyze the running time of this algorithm.

a. What are the basic operations you would count toward the running time?
b. What is the worst‐case running time as a total count (not big O) of these basic operations? c. What is the big O running time?
d. Is your algorithm linear, quadratic, or some other order?

SOLUTION

  1. Basic operations are addition and division.
  2. Each student total (which starts at zero) will be added to c times. Since there are r student totals,

    there are r*c additions for the totals.
    Each exam average will added to r times. Since there are c exams, this gives another c*r additions. Each exam average will be divided exactly once by the number of students, c. So, c divisions.

  3. O(rc)
  4. LINEAR (Note: The Big O looks like a quadratic value, but the INPUT SIZE is rc, and the running time is

linearly proportional to the input size.)

http://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps1_sol.html 1/3

9/17/2016 CS112 Fall 2016: Problem Set 1

3. Exercise 3.14, pg 118 of the textbook

A card game program keeps a deck of cards in an array. Give an algorithm to “unshuffle” the deck so that all the cards of a suit are grouped together, and within each suit, the cards are in ascending order or rank‐‐ consider the ace as the lowest ranked card. Since there are only 52 cards, space is not an issue so you can use extra space if needed. The only constraint is that your algorithm be as fast as possible.

What is the worst case big O running time of your algorithm? What are the basic operations you used in your analysis? Is the average big O running time different from the worst case?

SOLUTION

Allocate four new arrays, each of length 13, one for each suit. Go through the original deck from front to end, and slot each card in its appropriate position in the suit array to which it belongs. So for example the queen of hearts will go to index position 11 in the hearts array. Note that since the indexes of the arrays are from 0 through 12, the array position of a card will be one less than its face value. (Queen’s face value is 12, so its array position will be 11.)

The big O running time is O(1)!!

The basic operations are (a) looking up a card in the deck array, and (b) writing it into a suit array. Each of these takes unit time. (Writing takes unit time because the suit array is directly indexed with the card’s face value.) Since there are 52 look ups and 52 writes, the total number of basic operations, and therefore the total units of time, is 104. This is a constant, so the big O time is O(1).

Pay attention to this result, because what it says is that no matter how many actual operations you perform, because the input size is always the same, 52, the number of operations does not vary. Hence O(1).

4. * Exercise E3.11, page 118 of the textbook.
Two people compare their favorite playlists for matching songs. The first playlist has n songs, and the

second has m. Each is stored in an array, in no particular order.

1. Describe an algorithm to find the common songs in these lists (intersection), WITHOUT sorting either list.

  1. What is the worst‐case big O running time of your algorithm? Make sure to state the basic operations used in your analysis of running time.
  2. What is the best‐case big O running time of your algorithm? Explain clearly, including all book‐ keeping needed to achieve this best case.

2. Now suppose you could sort either or both arrays (as part of your algorithm). Repeat the worst‐case and best‐case analysis for the big O running time. (The running time must include the time to sort.)

SOLUTION

1. Algorithm: For each song in the first playlist, do a linear search in the second and if a match is found, add it to the output list.

Basic operation is a comparison between a pair of songs.

  1. In the worst case, there are no common songs. Every song in the first list gets compared with every song in the second, for a total of n*m comparisons, and therefore, O(n*m)
  2. In the best case, there is a maximum number of common songs, which would be min(m,n) (number of common songs cannot exceed the length of the smaller list). Also, the least number of comparisons is made to find a match. Again, doing a linear search for each song in the n list against the songs in the m list, the first song in the n list matches the first song in the m list (1 comparison), the second song in the n list matches the second song in the m list (2 comparisons), and so on. This gives a total of:

1+2+3+…+min(m,n)

http://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps1_sol.html 2/3

9/17/2016 CS112 Fall 2016: Problem Set 1

comparisons, which is O(min(m,n)2)
2. Use mergesort to sort each array. Then use the sorted lists merge algorithm to compare songs pair‐

wise and only keeping in the output the pairs that match.
1. Worst case: O(mlog m) + O(nlog n) + O(m+n) = O(mlog m + nlog n)
2. Best case: O(mlog m) + O(nlog n) + O(min(m,n)) = O(mlog m + nlog n)

5. ** Exercise E3.15, page 118 of the textbook.
There is a highway with n exists numbered 0 to n ‐ 1. You are given a list of the distances between them.

For instance:

Exits: 123456 Distances:5 3 4 2 8 6

The distance from the start of the highway to exit 1 is 5, from exit 1 to 2 is 3, and so on.

You have to devise an algorithm that would calculate the distance between any two exits. Imagine that this distance function is called millions of times by applications that need this information, so you need to make your algorithm as fast as possible.

Describe your algorithm. What is the worst‐case big O running time? Make sure to state all the parameters you use in the analysis and relate them to the algorithm.

SOLUTION
As the function that calculates the distance between any two exits is going to be called millions of times, it

should be as fast as possible, ideally O(1) We can achieve this speed by creating an array, S of distances of each exit from the start of the highway. Assume that the original distances between exits (as in the

example given in the problem) are in an array D

// copy distances between pairs of exits from D to S for(i=0;i<n;i++){

S[i] = D[i]; }

// compute distance (“sum”) from sta􏰂 for each exit for(i=1;i<n;i++){

S[i] = S[i-1] + S[i]; }

D:5 3 4 2 8 6 S:5 812142228

Creating the array takes linear time (O(n)) but using it will take constant time (O(1)). Once S is created, finding the distance from exit i to exit j is a simple matter of computing S[j] – S[i].

Running time Analysis

The basic operation for creating the S array is calculating the distance of each exit from the start of highway. It takes O(1) time for each exit and there are n exits. Therefore, it takes O(n) time.

The basic operation for finding the distance between two exits after we have the S array is a subtraction of two distance, both of which are obtained in constant time. So, O(1) time.

http://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps1_sol.html 3/3

10/8/2016 CS112 Fall 2016: Problem Set 2 Solution

Problem Set 2 ‐ Solution Linked Lists

1. WORK OUT THE SOLUTION TO THIS PROBLEM (ON PAPER, YOU DON’T NEED TO COMPILE AND RUN IT) AND TURN IT IN AT NEXT WEEK’S RECITATION

Assuming an IntNode class defined like this:

public class IntNode {
public int data;
public IntNode next;
public IntNode(int data, IntNode next) {

this.data = data; this.next = next; }

public String toString() { return data + “”;

}

Implement a method that will add a new integer before the last value in the linked list whose first node is pointed to by front. (In other words, the added integer will become the second‐to‐last item in the resulting

linked list.) The method should return a pointer/reference to the front node of the resulting linked list. If the input linked list is empty, the method should return null, without doing anything.

public static IntNode addBeforeLast(IntNode front, int item) { /* COMPLETE THIS METHOD */

}

SOLUTION

public static IntNode addBeforeLast(IntNode front, int item) { if (front == null) {

return null; }

IntNode prev=null, ptr=front; while (ptr.next != null) {

prev = ptr;

ptr = ptr.next; }

IntNode temp = Intnew Node(item, ptr); // next of new node should point to last if (prev == null) { // added item is 􏰃rst, so new node will be new front

return temp; }

prev.next = temp;

return front; // front is unchanged }

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps2_sol.html 1/5

10/8/2016 CS112 Fall 2016: Problem Set 2 Solution

2. Given the following definition of a StringNode class:

public class StringNode {
public String data;
public StringNode next;
public StringNode(String data, StringNode next) {

this.data = data; this.next = next; }

public String toString() { return data;

} }

Implement a method that will search a given linked list for a target string, and return the number of occurrences of the target:

public static int numberOfOccurrences(StringNode front, String target) { /* COMPLETE THIS METHOD */

}

SOLUTION

public static int numberOfOccurrences(StringNode front, String target) { int count=0;
for (StringNode ptr=front;ptr != null;ptr=ptr->next) {

if (target.equals(ptr.data)) { count++;

}

return count; }

3. * Assuming the IntNode class definition of problem 1, implement a method to delete EVERY OTHER item from an integer linked list. For example:

before: 3->9->12->15->21 a􏰄er: 3->12->21

before: 3->9->12->15 a􏰄er: 3->12

before: 3->9 a􏰄er: 3

before: 3 a􏰄er: 3

If the list is empty, the method should do nothing.

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps2_sol.html 2/5

10/8/2016 CS112 Fall 2016: Problem Set 2 Solution

public static void deleteEveryOther(IntNode front) { /* COMPLETE THIS METHOD */

}

SOLUTION

public static void deleteEveryOther(IntNode front) { if (front == null) {

return; }

Node prev=front, ptr=front.next; boolean tbd=true;
while (ptr != null) {

if (tbd) {
ptr=ptr.next; //advancetoa􏰄eritemtobedeleted prev.next = ptr; // bypass item to be deleted

} }

tbd = false; }else{

prev = ptr; ptr = ptr.next; tbd = true;

// next item should not be deleted
// don’t delete this (ptr) item, advance prev and ptr

// but mark next item for deletion

}
4. * With the same StringNode definition as in the previous problem, implement a method that will delete all

occurrences of a given target string from a linked list, and return a pointer to the first node of the resulting linked list:

public static StringNode deleteAllOccurrences(StringNode front, String target) { /* COMPLETE THIS METHOD */

}

SOLUTION

public static StringNode deleteAllOcurrences(StringNode front, String target) {

if (front == null) { return null;

}

StringNode curr=front, prev=null;

while (curr != null) {
if (curr.data.equals(target)) {

if (prev == null) { // target is the 􏰃rst element front = curr.next;

}else{
prev.next = curr.next;

} }else{

prev = curr; }

curr = curr.next;

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps2_sol.html 3/5

10/8/2016 CS112 Fall 2016: Problem Set 2 Solution

}

return front; }

5. * Implement a (NON‐RECURSIVE) method to find the common elements in two sorted linked lists, and return the common elements in sorted order in a NEW linked list. The original linked lists should not be modified. So, for instance,

l1 = 3->9->12->15->21 l2 = 2->3->6->12->19

should produce a new linked list:

3->12

You may assume that the original lists do not have any duplicate items. Assuming an IntNode class defined like this:

public class IntNode {
public int data;
public IntNode next;
public IntNode(int data, IntNode next) {

this.data = data; this.next = next; }

public String toString() { return data + “”;

}

Complete the following method:

// creates a new linked list consisting of the items common to the input lists // returns the front of this new linked list, null if there are no common items public IntNode commonElements(IntNode frontL1, IntNode frontL2) {

… }

SOLUTION

public IntNode commonElements(IntNode frontL1, IntNode frontL2) { IntNode 􏰃rst=null, last=null;
while (frontL1 != null && frontL2 != null) {

if (frontL1.data < frontL2.data) { frontL1 = frontL1.next

} else if (frontL1.data > frontL2.data) { frontL2 = frontL2.next;

}else{
IntNode ptr = new IntNode(frontL1.data, null); if (last != null) {

last.next = ptr; }else{

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps2_sol.html 4/5

10/8/2016 CS112 Fall 2016: Problem Set 2 Solution

􏰃rst = ptr; }

last = ptr;
frontL1 = frontL1.next; frontL2 = frontL2.next;

} }

return 􏰃rst; }

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps2_sol.html 5/5

10/8/2016 CS112 Fall 2016: Problem Set 3

Problem Set 3 ‐ Solution Linked Lists, Recursion

1. *Given the following definition of a circular linked list (CLL) class:

public class Node {
public String data;
public Node next;
public Node(String data, Node next) {

this.data = data; this.next = next; }

}

public class LinkedList {
private Node rear; // pointer to last node of CLL …

}
The class keeps a circular linked list, with a rear pointer to the last node.

Implement the following method in the LinkedList class, to delete the first occurrence of a given item from the linked list. The method returns true if the item is deleted, or false if the item is not found.

public boolean delete(String target) { /* COMPLETE THIS METHOD */

}

SOLUTION

public boolean delete(String target) {

if (rear == null) { // list is empty return false;

}

if (rear == rear.next) { // list has only one node
if (target.equals(rear.data)) { // found, delete, leaves empty list

rear = null;

return true; }else{ //notfound

return false; }

}

Node prev=rear, curr=rear.next; do{

if (target.equals(curr.data)) {
prev.next = curr.next;
if (curr == rear) { // if curr is last node, prev becomes new last node

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps3_sol.html 1/5

10/8/2016 CS112 Fall 2016: Problem Set 3

rear == prev; }

return true; }

// skip to next node prev = curr;
curr = curr.next;

} while (prev != rear);

return false; // not found }

2. * Implement a method in the circular linked list class of problem 1, to add a new item after a specified item. (If the new item happens to be added after the last, then it should become the new last item.) If the item does not exist in the list, the method should return false, otherwise true.

public boolean addA􏰄er(String newItem, String a􏰄erItem) throws NoSuchElementException {

/* COMPLETE THIS METHOD */ }

SOLUTION

public boolean addA􏰄er(String newItem, String a􏰄erItem) throws NoSuchElementException {

if (rear == null) { // empty return false;

}
Node ptr=rear; do{

if (a􏰄erItem.equals(ptr.data)) {
Node temp = new Node(newItem,ptr.next); ptr.next = temp;
if (ptr == rear) { // new node becomes last

rear = temp; }

return true; }

ptr = ptr.next;
} while (ptr != rear);
returnfalse; //a􏰄erItemnotinlist

}

3. A doubly linked list (DLL) is a linked list with nodes that point both forward and backward. Here’s an example:

3 <—> 5 <—> 7 <—> 1

Here’s a DLL node definition:

public class DLLNode { public String data;
public DLLNode prev, next;

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps3_sol.html 2/5

10/8/2016 CS112 Fall 2016: Problem Set 3

public DLLNode(String data, DLLNode next, DLLNode prev) { this.data = data; this.next = next; this.prev = prev;

} }

The next of the last node will be null, and the prev of the first node will be null. Implement a method to move a node (given a pointer to it) to the front of a DLL.

// moves target to front of DLL
public static DLLNode moveToFront(DLLNode front, DLLNode target) {

/** COMPLETE THIS METHOD **/ }

SOLUTION

// moves target to front of DLL
public static DLLNode moveToFront(DLLNode front, DLLNode target) {

if (target == null || front == null || target == front) { return;

}
// delink the target from the list
target.prev.next = target.next;
// make sure there is something a􏰄er target before se􏰅ing its prev if (target.next != null) {

target.next.prev = target.prev; }

target.next = front; target.prev = null; front.prev = target; return target;

}
4. With the same DLLNode definition as in the previous problem, implement a method to reverse the

sequence of items in a DLL. Your code should NOT create any new nodes ‐ it should simply resequence the original nodes. The method should return the front of the resulting list.

public static DLLNode reverse(DLLNode front) { /** COMPLETE THIS METHOD **/

}

SOLUTION

public static DLLNode reverse(DLLNode front) { if (front == null) {

return null; }

DLLNode rear=front, prev=null; while (rear != null) {

DLLNode temp = rear.next; rear.next = rear.prev; rear.prev = temp;
prev = rear;

rear = temp; }

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps3_sol.html 3/5

10/8/2016 CS112 Fall 2016: Problem Set 3

return prev; }

5. Implement a RECURSIVE method to delete all occurrences of an item from a (non‐circular) linked list. Use the Node class definition of problem 1. Return a pointer to the first node in the updated list.

public static Node deleteAll(Node front, String target) { /* COMPLETE THIS METHOD */

}

SOLUTION

public static Node deleteAll(Node front, String target) { if (front == null) { return null; }
if (front.data.equals(target)) {

return deleteAll(front.next, target); }

front.next = deleteAll(front.next, target);

return front; }

6. * Implement a RECURSIVE method to merge two sorted linked lists into a single sorted linked list WITHOUT duplicates. No new nodes must be created: the nodes in the result list are a subset of the nodes in the original lists, rearranged appropriately. You may assume that the original lists do not have any duplicate items.

For instance:

l1 = 3->9->12->15 l2 = 2->3->6->12

should result in the following:

2->3->6->9->12->15

Assuming a Node class defined like this:

public class Node { public int data; public Node next;

}

Complete the following method:

public static Node merge(Node frontL1, Node frontL2) { …

}

SOLUTION

public static Node merge(Node frontL1, Node frontL2) { if (frontL1 == null) { return front L2; }

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps3_sol.html 4/5

10/8/2016 CS112 Fall 2016: Problem Set 3

if (frontL2 == null) { return front L1; } if (frontL1.data == frontL2.data) {

// keep one copy
frontL1.next = merge(front1.next, frontL2.next); return frontL1;

}
if (frontL1.data < frontL2.data) {

frontL1.next = merge(front1.next, frontL2);

return frontL1; }

frontL2.next = merge(front2.next, frontL1);

return frontL2; }

7. ** Implement a RECURSIVE method to reverse the sequence of items in a linked list. The nodes of the

linked list are instances of the Node class defined in the previous problem. Your method should return a

pointer to the front node of the reversed list. It should NOT create any new nodes, only resequence the nodes of the original list.

public static Node reverse(Node front) {
/** COMPLETE THIS RECURSIVE METHOD **/

}

SOLUTION

public static Node reverse(Node front) { if (front == null || front.next == null) {

return front; }

Node rev = reverse(front.next); front.next.next = front; front.next = null;
return rev;

}

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps3_sol.html 5/5

10/8/2016 CS 112 Fall 2016 ­ Problem Set 4 Solution

Problem Set 4 ‐ Solution Sequential Search, Binary Search

  1. Given the following sequence of integers:

    3,9,2,15,-5,18,7,5,8

    1. What is the average number of comparisons for a successful search assuming all entries are searched with equal probability? Show your work.
    2. Suppose the search probabilities for the elements of this list are, respectively:

      0.1, 0.3, 0.05, 0.2, 0.05, 0.1, 0.05, 0.1, 0.05

      What is the average number of comparisons for successful search with these search probabilities?

      Show your work.

    3. Rearrange the list entries in a way that would result in the lowest number of comparisons on the

      average for successful search, given the above probabilities of search. What is this lowest number of comparisons? Show your work.

    SOLUTION

    In a sequential search of a list, it takes one comparison to succeed at the first element, two comparisons to succeed the second element, and so on. In general it takes i comparisons to succeed at the i‐th element. With the assumption that all entries are searched with equal probability, the formula is:

    (1+2+3+4+…+n)/n=n*(n+1)/2*n=(n+1)/2=(9+1)/2=5

    If the search probabilities are changed according to the given example, the average # of comparisons should be computed as follows:

    0.1×1+0.3×2+0.05×3+0.2×4+ 0.05×5+0.1×6+0.05×7 +0.1×8+0.05×9=4.1

    We should rearrange the entries such that entries with high search probabilities come first in the list. For example the entry “9” should be the first item since it has the highest search probability. Following this procedure, the new list should be arranged like this:

    9 15 {3,5,18} {2,-5,7,8}

    The entries in the brackets can be arranged in an arbitrary order since they have the same search probabilities.

  2. An adaptive algorithm to lower average match time for sequential search is to move an item by one spot toward the front every time it is matched. (Unless it is already at the front, in which case nothing is done on a match.) Complete the following modified sequential search on a linked list with this move‐toward‐ front adaption. Assume a generic Node class with data and next fields.

    public class LinkedList<T> { private Node<T> front; int size;

    // moves the target one place toward the front
    // doesn’t do anything if target is in the 􏰃rst node // returns true if target found, false otherwise public boolean moveTowardFront(T target) {

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps4_sol.html 1/6

10/8/2016 CS 112 Fall 2016 ­ Problem Set 4 Solution

// COMPLETE THIS METHOD }

SOLUTION

public boolean moveTowardFront(T target) { // COMPLETE THIS METHOD
Node ptr=front, prev=null;
while (ptr != null) {

if (ptr.data.equals(target)) { break;

}else{
prev = ptr; ptr = ptr.next;

} }

if (ptr == null) { // not found return false;

}
if (prev == null) { // front node, do nothing

return true; }

// switch with previous T temp = prev.data; prev.data = ptr.data; ptr.data = temp; return true;

}

3. Draw the comparison tree for binary search on a sorted array of length 11. 1. What is the worst case number of comparisons for success? For failure?

  1. What is the average number of comparisons for success, assuming equal likelihood of success at any

    spot?

  2. What can you say about the average number of comparisons for failure? Can you approximate it

    within a small range? Does it depend on the distribition of the probabilities of failing at the various failure spots?

SOLUTION
For the comparison tree, the nodes have the index positions where comparisons are made:

(5) = </ \>

= (2) (8) = </ \> </ \>

=(0) (3)= =(6) (9)=

</\></\> </\></\>
F (1)= F (4)= F (7)= F (10)=

</\> </\> </\> </\> FFFFFFFF

  1. Worst case #comparisons for success = 7 (for positions 1, 4, 7, 10), worst case #comparisons for failure = 8 (for failures off the positions 1, 4, 7, 10)
  2. Average #c for success = (1*1 + 2*3 + 4*5 + 4*7)/11 = 5

}

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps4_sol.html 2/6

10/8/2016 CS 112 Fall 2016 ­ Problem Set 4 Solution

3. It would take 6 comparisons to get to any of the failure nodes at the last but one level, and 8 comparisons for the last. So the average MUST be between 6 and 8, no matter what the probability distribution is over all of these possibilities.

4. * A variant of binary search, called lazy binary search, works as described in the following algorithm, where t is the target to search, and n is the size of the array:

le􏰄<–0
right <– n-1
while (le􏰄 < right) do

mid <– (le􏰄 + right)/2 if (t > A[mid]) then

le􏰄<–mid+1 else

right <– mid endif

endwhile
if (t == A[le􏰄]) then

display “found at position”, le􏰄 else

display “not found” endif

  1. Trace this algorithm on the following array, with 46 as the search target:

    10 15 25 30 45 46 48 72 76 80 93

    How many comparisons are made by the time a match is found? How does your answer compare with that for regular binary search?

    ANSWER

    4; while it takes 1 for regular binary search.

  2. Repeat with 40 as the target. How many comparisons are made until failure is detected? How does your answer compare with that for regular binary search?

    ANSWER

    5; while it takes 8 for regular binary search.

  3. Draw the comparison tree for lazy binary search on an array of length 11 (same length as the example array above).

    SOLUTION
    Actual values in the array are used instead of the index positions, for better clarity.

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps4_sol.html 3/6

10/8/2016 CS 112 Fall 2016 ­ Problem Set 4 Solution

Note that the comparison t > A[mid] is labeled on the right branch, and its flip (≯) is labeled on the

left branch, instead of against the A[mid] value itself because this makes for easier counting as you

descend the tree. (Only one comparison is actually made, so that whether you take the left or right branch, you will only count one comparison.) Also, for the comparison t == A[le􏰄] after exiting the

loop, the comparison is marked against the value in the tree, and the flip side of this comparison will result in falling through to the failure node.

  1. What is the worst case number of comparisons for success? For failure? ANSWER

    Worst case #comparisons for success = 5, same for failure

  2. What can you say about the range of values for the average number of comparisons for success? For failure?

    ANSWER

    Success happen at the last second‐to‐last and the third‐to‐last levels. For any success node in the second‐to‐last level the number of comparisons is 5, and for the third‐to‐last level is 4. So the average MUST be in the range 4 to 5.

    Failure happens at the last and second‐to‐last levels. For any failure node in the last level the number of comparisons is 5, and for the second‐to‐last level is 4. So the average MUST be in the range 5 to 6.

  3. Under what conditions is it preferable to use lazy binary search over the regular binary search? ANSWER

    Lazy binary search is better when there are more failures than successes since failures take fewer comparisons on average. While matches at certain positions now take longer to get to, the average number of comparisons is reduced since the new tree is less than double the height of the old, but the number of comparisons is halved. So, in sum, lazy binary search reduces the average number of comparisons for both successes and failures, and it levels the playing field over successes and failures.

5. An alternative algorithm for searching on a sorted array of size n works as follows. It divides the array into m contiguous blocks each of size s. (Assume that s divides into n without remainder).

Here is the algorithm to search for a key k in sorted array A.

Compare k with the last entry in the 􏰃rst block, i.e. A[s-1] If there is match, then stop with success

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps4_sol.html 4/6

10/8/2016 CS 112 Fall 2016 ­ Problem Set 4 Solution

Otherwise, check if k < A[s-1]
If so, pe􏰆orm a sequential search on the block of entries from A[0] to A[s-2]. If there is a match, stop with success, otherwise stop with failure.

If k is not < A[s-1] then continue the process by repeating the above on the second block, and so on.

a) * What is the worst case number of searches for success? SOLUTION

In the worst case, the last entry of every block is checked, and finally, a sequential search is performed in the last block. A total of 2m comparisons are made before the sequential search in the last block: 2 comparisons per last entry of each the m blocks. Then, the sequential search in the last block makes s‐1 comparisons. Total comparisons = 2m + s ‐1

b) ** What is the average case number of searches for success? SOLUTION

b) Compute the number of comparisons for each match, and then divide by number of entries. For first block matches:

item compares ——————–

last
􏰃rst
second
..
second last (s+1)

For second block matches: Before getting to the last item in the block, 2 comparisons (against the last item in the previous block). Then, within the block, the pattern is the same as in the previous table, so:

item compares ——————–

1 3

4

last
􏰃rst
second
..
second last (s+1) (+2)

For third block: Before getting to the last item in the block, 4 comparisons (2 comparisons against the last item in the 1st block, then 2 comparisons against the last item in the 2nd block.) Then, within block same as before, so:

item compares ——————–

1 (+2) 3 (+2)

last
􏰃rst
second
..
second last (s+1) (+4)

4 (+2)

1 (+4) 3 (+4)

4 (+4)

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps4_sol.html 5/6

10/8/2016 CS 112 Fall 2016 ­ Problem Set 4 Solution

So, the total looks like this:

(1+3+4+5+…+(s+1)) [1stblock]
+ (1+3+4+5+…+(s+1))+2*s [2ndblock,2addedtoeachofthesitems] + (1+3+4+5+…+(s+1))+4*s [3rdblock,4addedtoeachofthesitems] + ….
+ (1+3+4+5+…+(s+1))+2*(m-1)*s

Let the above sum be T. The average number of comparisons would be T/n. We can simplify T as follows. Let’s first take the series:

S = 1+3…+(s+1)

We can transform this to:

S = [1+2+3+…+(s+1)] – 2

Adding a 2 makes it an arithmetic series from 1 to (s+1), and we take away the 2 to compensate. This simplifies to:

S = (s+1)(s+2)/2 – 2
S occurs m times in T (once per block). So this component of T sums to:

m[(s+1)(s+2)/2-2]
Now let’s look at the other component of T, which is:

2s + 4s + … + 2(m-1)s = 2s[1+2+…(m-1)] = 2sm(m-1)/2 = n(m-1)

So now we have:

T = m[(s+1)(s+2)/2-2] + n(m-1) = m[(s^2 + 3s + 2)/2 -2] + n(m-1) =(ms*s+3ms+2m)/2-2m+n(m-1)=ns/2+3n/2+m-2m+nm-n=ns/2+n/2-m+nm

So average, T/n = s/2 + 1/2 – m/n + m

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps4_sol.html 6/6

10/16/2016 CS 112 Fall 2016 ­ Problem Set 5 Solution

Problem Set 5 ‐ Solution Stack, Array List, Queue

1. Suppose that the Stack class consisted only of the three methods push, pop, and isEmpty:

public class Stack<T> { …

public Stack() { … }
public void push(T item) { … }
public T pop() throws NoSuchElementException { … } public boolean isEmpty() { … }

}

Implement the following “client” method (i.e. not in the Stack class, but in the program that uses a stack):

public static <T> int size(Stack<T> S) { // COMPLETE THIS METHOD

}
to return the number of items in a given stack S.

Derive the worst case big O running time of the algorithm you used in your implementation. What are the dominant algorithmic operations you are counting towards the running time?

SOLUTION

Create another, temporary stack. Pop all items from input to temp stack, count items as you go. When all done, push items back from temp stack to input, and return count.

public static <T> int size(Stack<T> S) {

// COMPLETE THIS METHOD Stack<T> temp = new Stack<T>(); int count=0;
while (!S.isEmpty()) {

temp.push(S.pop());

count++; }

while (!temp.isEmpty()) { S.push(temp.pop());

}

return count; }

Note: There’s no try-catch around the S.pop() and temp.pop() calls because we know there won’t be an exception, since we only popping when the stack is not empty.

Dominant operations are push, pop. (isEmpty is auxiliary, used only as a stopping condition. The constructor

is only used once, so can be ignored since it is independent of the input stack size.) Each item in the stack is popped and pushed two times. For a stack of size n, this will add up to 4n pushes and pops, which gives a big O time of O(n).

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps5_sol.html 1/6

10/16/2016 CS 112 Fall 2016 ­ Problem Set 5 Solution

2. A postfix expression is an arithmetic expression in which the operator comes after the values (operands) on which it is applied. Here are some examples of expressions in their regular (infix) form, and their postfix equivalents:

In􏰃x Pos􏰇ix —————————-

22
2+3 23+ 2*(3+4) 234+* 2*(3-4)/5 234-*5/

Note that the postfix form does not ever need parentheses.

Implement a method to evaluate a postfix expression. The expression is a string which contains either single‐digit numbers (0‐‐9), or the operators +, ‐, *, and /, and nothing else. There is exactly one space between every two characters. The string has no leading spaces and no trailing spaces. You may assume that the input expression is not empty, and is correctly formatted as above.

You may find the following Stack class to be useful ‐ assume the constuctor and methods are already implemented.

public class Stack<T> {
public Stack() { … }
public push(T item) { … }
public T pop() throws NoSuchElementException { … } public T peek() throws NoSuchElementException { … } public boolean isEmpty() { … }

public void clear(T item) { … }

public int size (T item) { … } }

}

You may use the Character.digit(char,10) method to convert a character to the integer value it represents. For example, Character(‘2′,10) returns the integer 2. (The parameter 10 stands for the “radix” or base of the decimal number system.)

You may write helper methods (with full implementation) as necessary. You may not call any method that you have not implemented yourself.

public static 􏰈oat pos􏰇ixEvaluate(String expr) { /** COMPLETE THIS METHOD **/

}

SOLUTION:

public static 􏰈oat pos􏰇ixEvaluate(String expr) { Stack<Float> stk = new Stack<Float>();
for (int i=0; i < expr.length(); i++) {

char ch = expr.charAt(i); if(ch==”){continue;} if(ch==’+’||ch==’-‘||ch==’*’||ch==’/’){

􏰈oat second = stk.pop();
􏰈oat 􏰃rst = stk.pop();
switch (ch) {
case ‘+’: stk.push(􏰃rst + second); case ‘-‘: stk.push(􏰃rst – second);

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps5_sol.html 2/6

10/16/2016 CS 112 Fall 2016 ­ Problem Set 5 Solution

case ‘*’: stk.push(􏰃rst * second); case ‘/’: stk.push(􏰃rst / second); }
continue;

}

stk.push(Character.digit(ch,10); }

return stk.pop(); }

  1. This question compares the space usage for two versions of a stack, one using a linked list in which each node holds a reference to an object and a pointer to the next node, and the other using the Java ArrayList

    (array cells holding references to objects). Suppose the stack holds 1000 objects at its peak usage. How many bytes of space are used (a) by the linked list implementation, and (b) by the ArrayList

    implementation, at peak usage? Use the following data:
    A reference/pointer to an object uses 4 bytes of space.
    The ArrayList starts with an initial capacity of 10, and doubles each time it is resized.

    The linked list implementation keeps a “front” reference/pointer to the first node Both implementations keep an integer “size” field (4 bytes)
    The ArrayList implementation keeps an integer capacity field (4 bytes)

    SOLUTION

    Linked list implementation: 1000 nodes, each with two fields/8 bytes of space for 8000 bytes. Plus a front reference, 4 bytes, and a size field, 4 bytes, so 8008 bytes in all.
    Array list implementation: 1280 references at 4 bytes apiece, plus a size field and a capacity field, for 5128 bytes.

  2. Consider a smart array that automatically expands on demand. (Like the java.util.ArrayList.) It starts with some given initial capacity of 100, and whenever it expands, it adds 50 to the current capacity. So, for

    example, at the 101st add, it expands to a capacity of 150.

    How many total units of work would be needed to add 1000 items to this smart array? Assume it takes one unit of work to write an item into an array location, and one unit of work to allocate a new array.

    SOLUTION
    This is the sequence of adds and work:

    First 100 adds: 100 units for writes

    Expansion: 1 unit for allocation + 100 units to write from old to new Next 50 adds: 50 units for writes

    Expansion: 1 unit for allocation + 150 units to write from old to new Next 50 adds: 50 units for writes

    Expansion: 1 unit for allocation + 200 units to write from old to new Next 50 adds: 50 units for writes

    . . .

    To add 1000 elements, 18 expansions of 50 required (100+18*50=1000)
    Units of work done: 100 + (1+100+50)+ (1+150+50)+ (1+200+50)+ … (1+950+50)

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps5_sol.html 3/6

10/16/2016 CS 112 Fall 2016 ­ Problem Set 5 Solution

  1. Suppose you set up a smart array with an initial capacity of 5, with a DOUBLING of capacity every time there is a resize. What would be the average number of units of work per add, in the course of performing 100 adds? Assume the same work units as the previous exercise.

    SOLUTION
    We will expand the array 5 times: to 10, 20, 40, 80 and 160, one unit per expansion for a total of 5 units.

    Each time we expand, we have to copy the current length over. So cost for that will be 5+10+20+40+80 = 155.

    We will need to write 100 elements, which will cost 100 units.
    So total = 5 + 155 + 100 = 260. The average is 260/100 = 2.6 for each add.

  2. You are given the following Queue class:

    public class Queue<T> {
    public Queue() { … }
    public void enqueue(T item) { … }
    public T dequeue() throws NoSuchElementException { … } public boolean isEmpty() { … }
    public int size() { … }

    }
    Complete the following client method (not a Queue class method) to implement the peek feature, using

    only the methods defined in the Queue class:

    // returns the item at the front of the given queue, without // removing it from the queue
    public static <T> T peek(Queue<T> q)
    throws NoSuchElementException {

    /** COMPLETE THIS METHOD **/ }

    Derive the worst case big O running time of the algorithm that drives your implementation. What are the dominant algorithmic operations you are counting towards the running time?

    SOLUTION
    1. Version 1, using temporary queue and isEmpty() method

    // returns the item at the front of the given queue, without // removing it from the queue
    public static <T> T peek(Queue<T> q)
    throws NoSuchElementException {

    /** COMPLETE THIS METHOD **/ if (q.isEmpty()) {

    throw new NoSuchElementException(“Queue Empty”); }

    T result = q.dequeue();

    Queue<T> temp = new Queue<T>(); temp.enqueue(result);

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps5_sol.html 4/6

10/16/2016 CS 112 Fall 2016 ­ Problem Set 5 Solution

while(!q.isEmpty()) { temp.enqueue(q.dequeue());

}

while(!temp.isEmpty()) { q.enqueue(temp.dequeue());

}

return result; }

Dominant operations are enqueue and dequeue. Every item is enqueued twice and dequeued twice. For a queue of size n, this adds up to 4n operations, which is O(n) time.

2. Version 2, using size() method, no scratch queue needed

// returns the item at the front of the given queue, without // removing it from the queue
public static <T> T peek(Queue<T> q)
throws NoSuchElementException {

/** COMPLETE THIS METHOD **/ if (q.isEmpty()) {

throw new NoSuchElementException(“Queue Empty”); }

T result = q.dequeue(); q.enqueue(result);

// dequeue an element and enqueue it again for (size-1) elements // if there was only 1 element, this loop will not execute
for (int i=0; i < q.size()-1; i++) {

q.enqueue(q.dequeue()); }

return result; }

Dominant operations are enqueue and dequeue. For a queue of size n, there are n enqueques and dequeues each, for 2n operations, which gives O(n) time.

7. * Suppose there is a long line of people at a check‐out counter in a store. A new counter is opened, and people in the even positions (second, fourth, sixth, etc.) in the original line are directed to the new line. If a check‐out counter line is modeled using a Queue class, we can implement this “even split” operation in

this class.
Assume that a Queue class is implemented using a CLL, with a rear field that refers to the last node in the

queue CLL, and that the Queue class already contains the following constructors and methods:

public class Queue<T> {
public Queue() { rear = null; }
public void enqueue(T obj) { … }
public T dequeue() throws NoSuchElementException { … } public boolean isEmpty() { … }
public int size() { … }

}

Implement an additional method in this class that would perform the even split:

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps5_sol.html 5/6

10/16/2016 CS 112 Fall 2016 ­ Problem Set 5 Solution

// extract the even position items from this queue into // the result queue, and delete them from this queue public Queue<T> evenSplit() {

/** COMPLETE THIS METHOD **/ }

Derive the worst case big O running time of the algorithm that drives your algorithm. What are the dominant algorithmic operations you are counting towards the running time?

SOLUTION

// extract the even position items from this queue into // the result queue, and delete them from this queue public Queue<T> evenSplit() {

/** COMPLETE THIS METHOD **/

// Front of queue is at position 1, so we will extract 2nd, 4th, 6th, … Queue<T> evenQueue = new Queue<T>();
int originalSize = size();// size of this original queue

// iterate once over each pair of queue elements for (int pos=2; pos <= originalSize; pos += 2) {

// the 􏰃rst in a pair is recycled enqueue(dequeue());

// the second in a pair goes to result queue

evenQueue.enqueue(dequeue()); }

  • //  if original size was an odd number, we need to
  • //  recycle one more time if ((originalSize % 2) == 1) {

    enqueue(dequeue()); }

    return evenQueue; }

    Dominant operations are enqueue and dequeue. For a queue of size n, there are n enqueues and n dequeues, for a total of 2n opertions. So O(n) time.

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps5_sol.html 6/6

11/7/2016 CS112 Fall 2016: Problem Set 6 Solution

Problem Set 6 ‐ Solution Binary Search Tree (BST)

  1. Given the following sequence of integers:

    5, 15, 35, 10, 70, 25, 30, 75

    1. Starting with an empty binary search tree, insert this sequence of integers one at a time into this tree. Show the final tree. Assume that the tree will not keep any duplicates. This means when a new item is attempted to be inserted, it will not be inserted if it already exists in the tree.
    2. How many item‐to‐item comparisons in all did it take to build this tree? (Assume one comparison for equality check, and another to branch left or right.)

    SOLUTION

    (1) Following is the final tree. (2) Numbers in parentheses next to an item node indicate the number of comparisons required to insert that item.

    5 (0) \

    15 (2) /\

    (4)10 35(4) /\

    (6)25 70(6) \\

    (8)30 75(8)

    Total number of comparisons = 38.

  2. For the tree built in the above problem:
    1. What is the worst case number of comparisons for a successful search in this tree? For an

    unsuccessful (failed) search? (Assume one comparison for equality check, and another to branch left or right.)

    ANSWER

    5 /\ F 15

    /\ 10 35

    /\/\
    F F25 70

    /\/\
    F 30 F 75

    /\/\ FFFF

    Note: The ‘F’ nodes are not actual tree nodes ‐ they are failure positions.
    Successful search: 9 comparisons. (search for 30 or 75)
    Failed search: 10 comparisons (search for 26 thru 29, or 31 thru 34, or 70 thru 75, or values > 75 ‐ these will end up in one of the lowest level leaf nodes marked ‘F’ in the tree above.

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps6_sol.html 1/4

11/7/2016 CS112 Fall 2016: Problem Set 6 Solution

  1. What is the average case number of comparisons for a successful search in this tree? ANSWER

    Average case number of comparisons for successful search:

    5 (1) \

    15 (3) /\

    (5)10 35(5) /\

    (7)25 70(7) \\

    (9)30 75(9)

    Numbers in parentheses in the tree above indicate the number of comparisons to successfully search for the associated value in the tree. Total number of comparisons = 46. Total number of successful search positions = 8. Assuming equal probabilities of search for all successful search positions, average number of comparisons = 46/8.

  2. From this tree, delete 35: find the node (y) the largest value in its left subtree, write y’s value over 35, and delete y. How much work in all (locating 35, then locating y, then deleting y) did it take to complete the deletion? Count the target‐to‐item comparions as before, as well as 1 unit of work to descend one level in the tree, and 1 unit to delete at the end.

    ANSWER
    To delete 35, here is the work done:

    Locating 35: Number of comparisons is 5, plus 2 units to descend two levels (5‐>15, and 15‐ >35), so 7 in all.
    Locating y: The largest value in the left subtree of 35 is 30. Locating this requires a descent of 2 levels (35‐>25, 25‐>30), so 2 units.

    Deleting y (30): 1 unit So total is 7+2+1=10.

3. * Given the following BST node class:

public class BSTNode<T extends Comparable<T>> { T data;

BSTNode<T> le􏰄, right; public BSTNode(T data) {

this.data = data; this.le􏰄 = null; this.right = null;

}
public String toString() {

return data.toString(); }

}

Write a method to count all entries in the tree whose keys are in a given range of values. Your implementation should make as few data comparisons as possible.

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps6_sol.html 2/4

11/7/2016 CS112 Fall 2016: Problem Set 6 Solution

// Accumulates, in a given array list, all entries in a BST whose keys are in a given range,
// including both ends of the range – i.e. all entries x such that min <= x <= max.
// The accumulation array list, result, will be 􏰃lled with node data entries that make the cut. // The array list is already created (initially empty) when this method is 􏰃rst called.
public static <T extends Comparable<T>>
void keysInRange(BSTNode<T> root, T min, T max, ArrayList<T> result) {

/* COMPLETE THIS METHOD */ }

SOLUTION

public static <T extends Comparable<T>>
void keysInRange(BSTNode<T> root, T min, T max, ArrayList<T> result) {

if (root == null) { return;

}
int c1 = min.compareTo(root.data);
int c2 = root.data.compareTo(max); if(c1<=0&&c2<=0){ //min<=root<=max)

result.add(root.data); }

if(c1<0){
keysInRange(root.le􏰄, min, max, result);

} if(c2<0){

keysInRange(root.right, min, max, result); }

}

4. With the same BSTNode class as in the previous problem, write a method that would take a BST with keys arranged in ascending order, and “reverse” it so all the keys are in descending order. For example:

25 25 /\ /\

10 40 —> 40 10 /\/\ /\/\

2 2030 45 453020 2 /\ /\

15 35 35 15

The modification is done in the input tree itself, NO new tree is created.

public static <T extends Comparable<T>> void reverseKeys(BSTNode<T> root) {

/* COMPLETE THIS METHOD */

SOLUTION

public static <T extends Comparable<T>> void reverseKeys(BSTNode<T> root) {

if (root == null) { return;

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps6_sol.html 3/4

11/7/2016 CS112 Fall 2016: Problem Set 6 Solution

}
reverseKeys(root.le􏰄); reverseKeys(root.right); BSTNode<T> ptr = root.le􏰄; root.le􏰄 = root.right; root.right = ptr;

}

5. * A binary search tree may be modified as follows: in every node, store the number of nodes in its right subtree. This modification is useful to answer the question: what is the k‐th largest element in the binary search tree? (k=1 refers to the largest element, k=2 refers to the second largest element, etc.)

You are given the following enhanced binary search tree node implementation:

public class BSTNode<T extends Comparable<T>> { T data;
BSTNode<T> le􏰄, right;
int rightSize; // number of entries in right subtree …

}

Implement the following recursive method to find the k‐th largest entry in a BST:

public static <T extends Comparable<T>> T kthLargest(BSTNode<T> root, int k) { /* COMPLETE THIS METHOD */

}

SOLUTION Assume root is not null, and 1 <= k < n

public static <T extends Comparable<T>> T kthLargest(BSTNode<T> root, int k) {

if (root.rightSize == (k-1)) { return root.data;

}
if (root.rightSize >= k) {

return kthLargest(root.right, k); }

return kthLargest(root.le􏰄, k-root.rightSize-1); }

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps6_sol.html 4/4

11/7/2016 CS112 Fall 2016: Problem Set 7 Solution

Problem Set 7 ‐ Solution AVL Tree

1. * Each node of a BST can be filled with a height value, which is the height of the subtree rooted at that node. The height of a node is the maximum of the height of its children, plus one. The height of an empty tree is ‐1. Here’s an example, with the value in parentheses indicating the height of the corresponding node:

P(3) /\

M(1) V(2) //\

A(0) R(1) X(0) \

S(0)

Complete the following recursive method to fill each node of a BST with its height value.

public class BSTNode<T extends Comparable> { T data;

BSTNode<T> le􏰄, right; int height;

}

// Recursively 􏰃lls height values at all nodes of a binary tree public static <T extends Comparable>
void 􏰃llHeights(BSTNode<T> root) {

// COMPLETE THIS METHOD

… }

SOLUTION

// Recursively 􏰃lls height values at all nodes of a binary tree public static <T extends Comparable>
void 􏰃llHeights(BSTNode root) {

if (root == null) { return; } 􏰃llHeights(root.le􏰄); 􏰃llHeights(root.right); root.height = -1;

if (root.le􏰄 != null) { root.height = root.le􏰄.height;

}
if (root.right != null) {

root.height = Math.max(root.height, root.right.height); }

root.height++; }

2. In the AVL tree shown below, the leaf “nodes” are actually subtrees whose heights are marked in parentheses:

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps7_sol.html 1/7

11/7/2016 CS112 Fall 2016: Problem Set 7 Solution

—— D ——- /\

BF /\/\

ACEG /\/\/\/\

T1T2T3T4 T5T6T7T8 (h-1)(h)(h-1)(h-1)(h+1)(h)(h) (h)

1. Mark the heights of the subtrees at every node in the tree. What is the height of the tree? 2. Mark the balance factor of each node.

SOLUTION

Heights/Balance factors
A:h+1/right, C:h/equal, E:h+2/left, G:h+1/equal, B:h+2/left, F:h+3/left, D:h+4/right Height of the tree is h+4

3. Given the following AVL tree:

—J— /\ FT

/\/\ CHNX

/\/\/ BELQV

/\ OS

1. Determine the height of the subtree rooted at each node in the tree.

2. Determine the balance factor of each node in the tree.

3. Show the resulting AVL tree after each insertion in the following sequence: (In all AVL trees you show, mark the balance factors next to the nodes.)

Insert Z Insert P Insert A

SOLUTION 1 and 2:

Node Height ————————————–

B0- E0- C1- F2/ H0- O0- S0- Q1- L0- N2\ V0-

Balance factor

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps7_sol.html 2/7

11/7/2016 CS112 Fall 2016: Problem Set 7 Solution

X1/ T3/ J4\

3:
After Inserting Z:

—J— /\ FT

/\/\ CHNX-

/\/\/\ BELQVZ-

/\ OS

Only the balance factors of Z and X are changed; others remain the same After inserting P (in the tree above):

—J— /\ FT

/\/\ CHN\X-

/\/\/\
BE L/QVZ-

/\ \OS

\ -P

Insert P as the right child of O
Set bf of P to ‘‐’
Back up to O and set bf ‘\’
Back up to Q and set bf to ‘/’
Back up to N and stop. N is unbalanced, so rebalance at N.

Rebalancing at N is Case 2. First, rotate O‐Q

—J— /\ FT

/\/\ CHN\X-

/\/\/\ BELOVZ-

\ Q

/\ -PS

Then, rotate O‐N

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps7_sol.html 3/7

11/7/2016 CS112 Fall 2016: Problem Set 7 Solution

—J— /\ FT

/\/\
C H O- X-

/\/\/\
BE /N-QVZ-

//\ -L -P S

After inserting A (in the tree above):

—J— /\ FT

/\/\
/C H O- X- /\/\/\

/BE /N-QVZ- ///\

-A

Insert A as Set bf of A Back up to Back up to Back up to

-L -P S

the left child of B
to ‘‐’
B and set bf to ‘/’
C and set bf to ‘/’
F and stop. F is unbalanced, so rebalance at F.

Rebalancing at F is Case 1. Rotate C‐F

—J— /\

-C T /\/\

/B-F O-X-

//\ /\/\
-A -EH-/N -Q V Z-

//\ -L -P S

4. Starting with an empty AVL tree, the following sequence of keys are inserted one at a time:

1,2,5,3,4

Assume that the tree allows the insertion of duplicate keys.

What is the total units of work performed to get to the final AVL tree, counting only key‐to‐key comparisons and pointer assignments? Assume each comparison is a unit of work and each pointer assignment is a unit of work. (Do not count pointer assignments used in traversing the tree. Count only assignments used in changing the tree structure.)

SOLUTION

Since the tree allows duplicate keys, only one comparison is needed at every node to turn right (>) or left (not >, i.e. <=) when descending to insert.

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps7_sol.html 4/7

11/7/2016 CS112 Fall 2016: Problem Set 7 Solution

To insert 1: 0 units

1

To insert 2: 1 comparison + 1 pointer assignment = 2 units

1 \

2

To insert 5: 2 comparisons + 1 pointer assignment:

1 \

2 \

5

Then rotation at 2‐1, with 3 pointer assignments:

root=2, 2.le􏰄=1, 1.right=null

Total: 2+1+3 = 6 units, resulting in this tree:

2 /\ 15

To insert 3: 2 comparisons + 1 pointer assignment = 3 units:

2 /\ 15

/ 3

To insert 4: 3 comparisons + 1 pointer assignment:

2 /\ 15

/ 3 \

4

Then a rotation at 4‐3, with 3 pointer assignments:

2 /\

1 5 Pointerassignments:5.le􏰄=4,3.right=null,4.le􏰄=3 /

4 /

3

And a rotation at 4‐5, with 3 pointer assignments:

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps7_sol.html 5/7

11/7/2016 CS112 Fall 2016: Problem Set 7 Solution

2 /\

1 4 Pointerassignments:2.right=4,4.right=5,5.le􏰄=null /\

35

Total: 10 units
Grand total: 21 units of work

5. * After an AVL tree insertion, when climbing back up toward the root, a node x is found to be unbalanced. Further, it is determined that x’s balance factor is the same as that of the root, r of its taller subtree (Case 1). Complete the following rotateCase1 method to perform the required rotation to rebalance the tree at node x. You may assume that x is not the root of the tree.

public class AVLTreeNode<T extends Comparable<T>> { public T data;
public AVLTreeNode<T> le􏰄, right; publiccharbalanceFactor; //’-‘or’/’or’\’

public AVLTreeNode<T> parent;

public int height; }

public static <T extends Comparable<T>> void rotateCase1(AVLTreeNode<T> x) {

// COMPLETE THIS METHOD }

SOLUTION

public static <T extends Comparable<T>> void rotateCase1(AVLTreeNode<T> x) {

// r is root of taller subtree of x
r = x.balanceFactor == ‘\’ ? x.right : x.le􏰄;
if (x.parent.le􏰄 == x) { x.parent.le􏰄 = r; } else { x.parent.right = r; } r.parent = x.parent;
if (x.balanceFactor == ‘\’) { // rotate counter-clockwise

AVLTreeNode temp = r.le􏰄; r.le􏰄 = x;
x.parent = r;
x.right = temp; x.right.parent = x;

} else { // rotate clockwise AVLTreeNode temp = r.right; r.right = x;
x.parent = r;

x.le􏰄 = temp;

x.le􏰄.parent = x; }

//changebfsofrandx
x.balanceFactor = ‘-‘;
r.balanceFactor = ‘-‘;
// x’s height goes down by 1, r’s is unchanged x.height–;

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps7_sol.html 6/7

11/7/2016 CS112 Fall 2016: Problem Set 7 Solution

}

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps7_sol.html 7/7

11/7/2016 CS112 Fall 2016: Problem Set 8 Solution

Problem Set 8 ‐ Solution Binary Tree, Huffman Coding

1. * Answer the following questions in terms of h, the height of a binary tree:

  1. What is the minimum possible number of nodes in a binary tree of height h?
  2. A strictly binary tree is one in which every node has either no children or two children; in other

    words, there is no node that has exactly one child. What is the minimum possible number of nodes in

    a strictly binary tree of height h?

  3. A complete binary tree is one in which every level but the last has the maximum number of nodes

    possible at that level; the last level may have any number of nodes. What is the minimum possible number of nodes in a complete binary tree of height h?

SOLUTION

  1. h+1 ‐ one node at every level, and there are (h+1) levels (levels are numbered 0, 1, …, h)
  2. Every level except the root level has 2 nodes. So, 1 + 2*h
  3. Level 0 has 20 nodes, level 1 has 21 nodes, and so on. Level h‐1 has 2(h‐1) nodes. The last level has one node. The total is 2h‐1+1 = 2h.

2. Two binary trees are isomorphic if they have the same shape (i.e. they have identical structures.) Implement the following recursive method:

public static <T> boolean isomorphic(BTNode<T> T1, BTNode<T> T2) { /* your code here */

}
that returns true if the trees rooted at T1 and T2 are isomorphic, and false otherwise. BTNode is defined as

follows:

public class BTNode<T> { T data;

BTNode<T> le􏰄, right;
BTNode(T data, BTNode<T> le􏰄, BTNode<T> right) {

this.data = data; this.le􏰄 = le􏰄; this.right = right;

} }

SOLUTION

public static <T> boolean isomorphic(BTNode<T> T1, BTNode<T> T2) { if (T1 == null && T2 == null) return true;
if (T1 == null || T2 == null) return false;
if (!isomorphic(T1.le􏰄, T2.le􏰄)) return false;

return isomorphic(T1.right, T2.right); }

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps8_sol.html 1/9

11/7/2016 CS112 Fall 2016: Problem Set 8 Solution

3. The radix tree data structure shown below stores the bit strings 0,1,01,010,100, and 1011 in such a way that each left branch represents a 0 and each right branch represents a 1.

X /\ 01 \/ 01 X //\

010 100 X \

1011

Nodes that do not have any stored bit strings will have a dummy value ‘X’ instead.

To find whether a bit string exists in this radix tree, start from the root, and scanning the bits of the string left to right, take a left turn if the but is 0, and a right turn if the bit is 1. If a node can be reached using this sequence of turns, and it does not contain the dummy value ‘X’, then the bit string is found, else it is not found.

  1. Given the following bit strings:

    1011, 01, 0010, 1010, 011, 1000, 0101

    Starting with an empty radix tree, build it up to store these strings, showing the radix tree after each bit string is inserted. (To insert a new string you may have to insert more than one new node in the tree built thus far.)

  2. How many units of time did it take to build this tree? Treat taking a turn at an existing branch, and inserting a new branch as basic unit time operations.
  3. How many units of time would it take to lexicographically sort the bit strings in this radix tree, after all the strings have been inserted? Use the same basic operations as in the previous question. The output of the sort should be:

    0010 01 0101 011 1000 1010 1011

    (Lexicographic sort is like alphabetic sort, 0 precedes 1)

  4. How many units of time would it take in the worst case to insert a new k‐bit string into a radix tree?

    (ANY radix tree, not the specific one above.)

  5. How many units of time would it take in the worst case to insert an arbitrary number of bit strings

    whose total length is n bits?

SOLUTION

1. After inserting 1011:

x \

x /

x \

x \

1011

After inserting 01:

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps8_sol.html 2/9

11/7/2016 CS112 Fall 2016: Problem Set 8 Solution

x /\ xx \/

01 x \

x \

1011

After inserting 0010:

x /\ xx

/\/ x 01 x

\\ xx /\

0010 1011

After inserting 1010:

x /\ xx

/\/ x 01 x \\

xx //\

0010 1010 1011

After inserting 011:

x /\

xx /\/

x 01 x \\\

x 011 x //\

0010 1010 1011

After inserting 1000:

x /\ /\

xx /\/

x 01 x \\/\

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps8_sol.html 3/9

11/7/2016 CS112 Fall 2016: Problem Set 8 Solution

x011x x ///\

0010 1000 1010 1011

After inserting 0101:

x /\ /\ xx

/\/ x01 x

\/\/\ xx011x x

/\//\
0010 0101 1000 1010 1011

  1. The number of turns plus new branches is equal to the length of the string being added. So total units of time is 4 + 2 + 4 + 4 + 3 + 4 + 4 = 25.
  2. The lexicographic sort is equivalent to a preorder traversal on the radix tree, printing only at the nodes that have values. The first value that is printed, 0010, will need 4 turns starting from the root. Then the preorder traversal will eventually print 01, after backtracking to the parent of 01 and then taking a right turn to get to 01. Backtracking does not count for turns since it is implemented automatically in the recursion.

    The turns for all strings are as follows:

    0010: 4 (from root)
    01: 1 (right subtree from great-grandparent of 0010) 0101: 2 (le􏰄 subtree from 01)
    011: 1 (right subtree from 01)
    1000: 4 (from root)
    1010: 2 (right subtree from grandparent of 1000) 1011: 1 (right subtree from parent of 1010)

    ————- Total: 15 ————-

  3. To insert a binary string of k bits would require k turns/new branches, so k units of time.
  4. For an arbitrary number of bit strings whose total length is n, the total number of turns/new

    branches would be n, so n units of time.

4. A general tree is one in which a node can have any number of children. General trees are used to model hierarchies. Think of a company hierarchy with a CEO at the root, then presidents of various units that report to her at the next level, then various vice‐presidents who report to the presidents at the next level, and so on. Computer file systems are hierarchies as well, with a root folder, with other folders and files recursively nested under the root.

Every general tree can be represented as a binary tree. Here’s an example of how:

A
____|_____ A |||| / BCDX B

/\|\ EFG C

/\ ED

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps8_sol.html 4/9

11/7/2016 CS112 Fall 2016: Problem Set 8 Solution

\\ FX

/ G

For every node in the general tree:
The first child of the node becomes the left child of the same node in the binary tree The second child of the node becomes the right child of the first
The third child of the node becomes the right child of the second, and so on

1. Exercise 9.8 of text
Draw the binary tree representations of the following general trees:

(a) (b) (c)

AAA
_____|_____ _____|_____ _____|______

||| ||| ||||
GHK GHK GHKZ |/\|||||||
BXP XPQ BXPE

____|____ | | | /\ /\ |||| RTSOLNR OLRE

SOLUTION

(a) (b) (c)

AAA ///

GGG /\/\/\

BHXHBH //\ //\ //\

OXK RPK OXK \\//\/\

LP TQ LPZ \///

RSNE \\

ER

2. Exercise 9.9 of text
Draw the general trees represented by the following binary trees:

(a) (b) (c)

ATA ///

GDB /\/\\

BLGRC /\\/\/\/

ORE PQEX D

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps8_sol.html 5/9

11/7/2016 CS112 Fall 2016: Problem Set 8 Solution

/\/\ \ ACBD E

SOLUTION

(a) (b) (c)

ATA
_____|_____ _____|_____ __|__

|||||| ||

GLEDRX BC / \ ___|___ | / \

BR |||E DE | GQD
O /\|

PCB |
A

5. Suppose the equivalent binary tree for a general tree is built out of the following binary tree nodes:

public class BTNode<T> {
T data;
BTNode<T> le􏰄, right, parent; …

}

Complete the following methods
1. Given a pointer to a node x, find and return the node that would be x’s parent in the general tree:

public static <T> BTNode<T> genTreeParent(BTNode<T> x) { /* COMPLETE THIS METHOD */

}

SOLUTION

public static <T> BTNode<T> genTreeParent(BTNode<T> x) { while (x.parent != null) {

if (x == x.parent.le􏰄) { return x.parent;

}

x = x.parent; }

return null; }

2. * Given a pointer to a node x, and an integer k, find and return the node that would be the k‐th child of x (k=1 if first child, etc.), in the general tree. The method should thrown an exception if there is no k‐th child:

public static <T> BTNode<T> genTreekthChild(BTNode<T> x, int x) throws NoSuchElementException {

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps8_sol.html 6/9

11/7/2016 CS112 Fall 2016: Problem Set 8 Solution

/* COMPLETE THIS METHOD */ }

SOLUTION

public static <T> BTNode<T> genTreekthChild(BTNode<T> x, int k) throws NoSuchElementException {

if(k<=0||x.le􏰄==null){
throw new NoSuchElementException();

}
x = x.le􏰄; k–;
while (k > 0 && x.right != null) {

x = x.right;

k–; }

if(k>0&&x.right==null){//k>#children throw new NoSuchElementException();

}

return x; }

6. * Suppose you are given the following binary tree class definition, which uses the BTNode<T> class of the previous exercise.

public class BinaryTree<T> { private BTNode<T> root; …

}

Add the following methods to this class so that applications can do an inorder traversal one node at a time:

// returns the 􏰃rst node that would be visited in an inorder traversal // null if tree is empty
public BTNode<T> 􏰃rstInorder() {

/* COMPLETE THIS METHOD */ }

SOLUTION

// returns the 􏰃rst node that would be visited in an inorder traversal; // returns null if tree is empty
public BTNode<T> 􏰃rstInorder() {

if (root == null) { return null;

}
// le􏰄 most node in tree is the 􏰃rst node in inorder BTNode<T> prev=root, ptr=root.le􏰄;
while (ptr != null) {

prev = ptr;

ptr = ptr.le􏰄; }

return prev; }

and

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps8_sol.html 7/9

11/7/2016 CS112 Fall 2016: Problem Set 8 Solution

// returns the next node that would be visited in an inorder traversal; // returns null if there is no next node
public BTNode<T> nextInorder(BTNode<T> currentNode) {

if (currentNode == null) { // playing defense here return null;

}
// if there is a right subtree, then right turn, and le􏰄 all the way to bo􏰅om if (currentNode.right != null) {

BTNode<T> ptr=currentNode.right; while (ptr.le􏰄 != null) {

ptr = ptr.le􏰄; }

return ptr; }

// no right subtree
BTNode<T> p = currentNode.parent;
while (p != null && p.right == currentNode) {

currentNode = p;

p = p.parent; }

return p; }

For instance, an application would call these methods like this to do the inorder traversal:

BinaryTree<String> strBT = new BinaryTree<String>(); // inse􏰂 a bunch of strings into strBST

// do inorder traversal, one node at a time BTNode<String> node = strBST.􏰃rstInorder();

while (node != null) {
node = strBST.nextInorder(node);

}

7. Exercise 9.4, page 295 of the textbook.

  1. Build a Huffman tree for the following set of characters, given their frequencies:

    RCLBHAE 6 6 610152037

  2. Using this Huffman tree, encode the following text:

    CLEARHEARBARE

  3. What is the average code length?
  4. If it takes 7 bits to represent a character without encoding, then for the above text, what is the ratio of the encoded length to the unencoded?
  5. Decode the following (the string has been broken up into 7‐bit chunks for readability):

    1111011 1010111 1101110 0010011 111000

SOLUTION

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps8_sol.html 8/9

11/7/2016 CS112 Fall 2016: Problem Set 8 Solution

1. The probabilities of occurence of the characters, listed in ascending order:

RCLBHAE
0.06 0.06 0.06 0.1 0.15 0.2 0.37

1.0 0/ \1

/\
E 0.63

0/ \1 /\

0.27 0.36 0/ \1 0/ \1

/\/\ 0.12 H 0.16 A

0/ \10/ \1 /\/\

RCLB

R 1000 C 1001 L 1100 B 1101 A 111

H 101 E0

  1. 100111000111100010101111000110111110000
  2. 1*0.37 + 4*0.06 + 4*0.06 + 3*0.15 + 4*0.06 + 4*0.10 + 3*0.20 = 2.54
  3. Length of unencoded representation using 7 bits per character is 7*13=91, while length of representation using Huffman codes is 39. The ratio of encoded to unencoded is 39/91.
  4. AHBEABLECAR

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps8_sol.html 9/9

11/12/2016 CS112 Spring 2016: Problem Set 9 Solution

Problem Set 9 ‐ Solution Hash table

1. You are given the following keys to be hashed into a hash table of size 11:

96, 43, 72, 68, 63, 28

Assume the following hash function is used

H(key) = key mod 11

and chaining (array of linked lists) is used to resolve collisions.

1. Show the hash table that results after all the keys are inserted.
2. Compute the average number of comparisons for successful search.

SOLUTION
1. 0 []->/

1 []->/
2 []->68->/
3 []->/
4 []->/
5 []->/
6 []->28->72->/ 7 []->/
8 []->63->96->/ 9 []->/ 10[]->43->/

2. The average number of comparisons for successful search is:

(1+1+2+1+2+1)/6 = 4/3

2. Using chaining to resolve collisions, give the worst‐case running time (big O) for inserting n keys into an initially empty hash table table for each of the following kinds of chains:

Chain is an unordered list
Chain is an ordered list (entries stored in ascending order of keys) Chain is an AVL tree (ordered by keys)

SOLUTION
In the worst case, ALL n entries are in the same chain.

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps9_sol.html 1/4

11/12/2016 CS112 Spring 2016: Problem Set 9 Solution

Chain is an unordered list
Every new entry is inserted at the front of the list, in O(1) time. For n, the total time is O(n)

Chain is an ordered list (entries stored in ascending order of keys)
In the worst case, every new entry is to be added to the end of the chain. The first entry is added in 1 step, the second in 1 step, third in 2 steps, etc. The total time is:

1+1+2+…n-1

which sums to O(n^2)

Chain is an AVL tree (ordered by keys)
Each insert takes logarithmic time in the size of the AVL tree (size includes the inserted entry). The first entry takes unit time to insert, the subsequent entries sum up to the following:

log(2)+log(3)+…+log(n)

This simplies to O(nlog n)

3. Using the following class definitions:

class Node { int key;

String value;

Node next; }

class Hashtable {
Node[] entries;
int numvalues;
􏰈oat max_load_factor;
public Hashtable(􏰈oat max_load_factor) { … } // constructor

}

Complete the following methods of the Hashtable class, using the hash function h(key) = key mod table_size.

public void inse􏰂(int key, String value) { // COMPLETE THIS METHOD

}

private void rehash() {
// COMPLETE THIS METHOD

}

Note: When expanding the hash table, double its size. SOLUTION

public void inse􏰂(int key, String value) { int index = key % entries.length(); Node e = new Node();
e.key = key;

e.value = value;
e.next = entries[index];
entries[index] = e;
numvalues++;
􏰈oat load_factor = (double)numvalues / entries.length;

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps9_sol.html 2/4

11/12/2016 CS112 Spring 2016: Problem Set 9 Solution

if (load_factor > max_load_factor) { rehash();

} }

private void rehash() {
Node oldEntries[] = entries;
int oldCapacity = oldEntries.length(); int newCapacity = 2*oldCapacity; entries = new Node[newCapacity]; numvalues=0; for(inti=0;i<oldCapacity;i++){

for (Node e = oldEntries[i] ; e != null ; e = e.next) { inse􏰂(e.key, e.value);

} }

}

4. Suppose you are asked to write a program to count the frequency of occurrence of each word in a document. Desrcibe how you would implement your program using:

1. A hash table to store words and their frequencies.

2. An AVL tree to store words and their frequencies. For each of these implementations:

1. What would be the worst case time to populate the data structure with all the words and their frequencies?

  1. What would be the worst case time to look up the frequency of a word?
  2. What would be the worst case time to print all words and their frequencies, in alphabetical order of

    the words?

Assume there are n distinct words in the document, and a total of m words, and m is much greater than n.

SOLUTION Implementation Process:

  1. Hash table: For each word, hash and search in the chain at that location. If word already exists, then increment frequency by 1, otherwise add it with frequency 1. (So key is word, and value is frequency.)
  2. AVL tree: Tree ordering is alphabetical on words. (In other words, search compares words, and each node in the tree has a word and its frequency.) For each word, search for it in the tree. If it exists, increment its frequency by 1, otherwise add it with frequency 1.

Running times:
1. Populating the data structure

1. Hash table:

In the worst case, all words hash to the same location, giving a chain of length n. In order to push the running time to the worst possible, the scenario to consider is when the first n words in the document are the distinct words, and the following (m‐n) words are duplicates of the first n

To add the first n words would take time:

1+2+3+…+n=O(n^2)

Since a word is first searched to see if it exists, and a worst case search will be all the way down the chain, the first and add takes 1 unit of time, the second takes 2 units, etc.

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps9_sol.html 3/4

11/12/2016 CS112 Spring 2016: Problem Set 9 Solution

The subsequent m‐n words would each be searched on a chain of length n, with the worst case search running all the way through the chain, for n units of time. So this would amount of a time of (m‐n)*n. Since m is much greater than n, this amounts to O(mn) time.

So the total time is:

O(n^2) + O(mn)

and again, since m much greater than n, this simplifies to O(mn). 2. AVL Tree:

With the same scenario for the worst case as above (distinct words all up front): The first n inserts would take time:
log1+log2+log3…+logn=log(n!)

There’s a math quantity called Stirling’s formula that says n! is approximately equal to (n/2)^(n/2):

log (n!) is approximately = log ((n/2)^(n/2)) = O(n log n)

The subsequent (m‐n) searches would in the worst case take O(log n) time each, and since m is much greater than n, this results in O(m log n) time

2. Looking up the frequency of a word
1. Hash table: O(n), since the longest chain is of length n
2. AVL Tree: O(log n), since the height of the tree is O(log n)

3. Printing words,frequencies in alphabetical order of words
1. Hash table: Since there is no relative ordering of the words in the hash table, all the words

need to be retrieved (with their frequencies), then sorted. The retrieval will take O(n) time, and the sorting will take O(nlog n) time (using mergesort, for example). So the total time is O(nlog n).

2. AVL tree: Since the tree is already ordered alphabetically by words, an inorder traversal will do the trick, in only O(n) time.

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps9_sol.html 4/4

11/23/2016 CS112 Spring 2016: Problem Set 10

Problem Set 10 ‐ Solution Heap

1. Given the following sequence of integers:

12,19,10,4,23,7,45,8,15

  1. Build a heap by inserting the above set, one integer at a time, in the given sequence. Show the heap after every insertion. How many comparisons in all did it take to build the heap?
  2. Perform successive delete operations on the heap constructed in the previous step, until the heap is empty. Show the heap after every deletion. How many comparisons in all did it take to perform these deletions?

SOLUTION

1. The heaps built one at a time are shown in the following table. The first column is the item that is inserted, the second column is the heap after this item is inserted (indicated by its level order traversal), and the third column is the number of item‐to‐item comparisons made by the sift up process.

Inse􏰂 Heap a􏰄er inse􏰂ion Number of comparisons ——————————————————————– 1212 0
19 1912 1

10 191210 1
4 1912104 1
23 231910412 2
7 2319104127 1
45 451923412710 2 8 4519238127104 2 15 451923151271048 2

Total # of comparisons = 12

2. The left column shows the heap (level order traversal representation) after deleting the top of the heap, and the right column shows the number of item‐to‐item comparisons made by the sift‐down process.

Heap a􏰄er deletion Number of comparisons ————————————————- 2319101512784 4
19151041278 4

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps10_sol.html

1/4

11/23/2016 CS112 Spring 2016: Problem Set 10

151210487 4 1281047 4 10874 2 847 2 741 40 empty 0

Total number of comparisons = 21

  1. Suppose we have a (max) heap that stores integers. (By contrast, in a “min” heap the key at any node is less than or equal to the key at its children, so the smallest valued key is at the top of the heap.) Then, given an integer k, we would like to print all the values in this heap that are greater than k. Implement the following method to do this.

    public void printGreater(int[] H, int n, int k) { /* your code here */

    }

    H is the array storage for the max heap, and n is the number of entries in the heap.
    Note: The challenge is to do this efficiently. Use the heap order to reduce the number of entries of the heap to be examined. SOLUTION

    public void printGreater(int[] H, int n, int k) { recursivePrintGreater(H, n, k, 0);

    }

    private void recursivePrintGreater(int[] H, int n, int k, int rootIndex) { if (rootIndex >= n) return; // out of bounds
    if (H[rootIndex] <= k) return; // all values <= k in this sub-heap System.out.println(H[rootIndex]); // print root value recursivePrintGreater(H, n, k, 2*rootIndex+1); // le􏰄 sub-heap recursivePrintGreater(H, n, k, 2*rootIndex+2); // right sub-heap

    }

  2. Consider a max heap that only supports the operations insert, deleteMax, size, and isEmpty. A client of the heap wants to update the priority of an entry in the heap. Since there is no search operation, the only way to accomplish the update is this:

    Perform successive deleteMax operations until the entry is extracted Update the entry’s priority
    Insert the entry, as well as all the other deleted entries back into the heap

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps10_sol.html

2/4

11/23/2016 CS112 Spring 2016: Problem Set 10

What would be the worst case running time (big O) of this update process on a heap with n entries?
SOLUTION
In the worst case, n deletes and n inserts would need to be done. The time for the deletes is as follows (approximated for big O):

logn+log(n-1)+log(n-2)+….+1=log(n!)=O(n*logn)

The total time for the inserts is also O(n*logn ) by a similar argument. The update process is therefore O(n*log n)

4. * Suppose you are given two heaps, stored in arrays. Write a method to merge them into a single heap, and return this heap. The original heaps are not modified:

public static <T extends Comparable<T>> T[] merge(T[] heap1, T[] heap2) { // COMPLETE THIS METHOD

}

SOLUTION

public static <T extends Comparable<T>> T[] merge(T[] heap1, T[] heap2) { T[] res = (T[])new Object[heap1.length + heap2.length];
for (int i=0; i < heap1.length; i++) {

res[i] = heap1[i]; }

for (int i=0; i < heap2.length; i++) { res[i+heap1.length] = heap2[i];

}

// in res, si􏰄 up sta􏰂ing with entries copied from the second heap for (int s=heap1.length; s < res.length; s++) {

int k=s;
// si􏰄 up res[k] while(k>0){

int p = (k-1)/2;
if (res[k].compareTo(res[p]) > 0) { // switch

T temp = res[k]; res[k] = res[p]; res[p] = temp;

k=p; }else{

break; }

}

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps10_sol.html

3/4

11/23/2016 CS112 Spring 2016: Problem Set 10

}

return res; }

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps10_sol.html

4/4

12/16/2016 CS112 Fall 2016: Problem Set 11

Problem Set 11 ‐ Solution Graphs: Representation, Traversal

  1. Suppose a weighted undirected graph has n vertices and e edges. The weights are all integers. Assume that the space needed to store an integer is the same as the space needed to store an object reference, both equal to one unit. What is the minimum value of e for which the adjacency matrix representation would require less space than the adjacency linked lists representation? Ignore the space needed to store vertex labels.

    SOLUTION

    Space for adjacency matrix (AMAT) is n^2. Space for adjacency linked lists (ALL) is n + 3*2e = n + 6e. (Each node needs 3 units of space: 1 for the neighbor number, 1 for the edge weight, and 1 for the next node reference. And there are 2e nodes.) The space required by AMAT and ALL is the same when n^2 = n + 6e, i.e. when e = (n^2 ‐ n)/6.

    The minimum value of e for which the adjacency matrix representation would require less space than the adjacency linked lists representation is one more than the e above, which would be (n^2 ‐ n)/6+1.

  2. The complement of an undirected graph, G, is a graph GC such that:
    GC has the same set of vertices as G
    For every edge (i,j) in G, there is no edge (i,j) in GC
    For every pair of vertices p and q in G for which there is no edge (p,q), there is an edge (p,q) in GC.

    Implement a method that would return the complement of the undirected graph on which this method is applied.

    class Edge { int vnum; Edge next;

    }

    public class Graph {
    Edge[] adjlists; // adjacency linked lists …
    public Graph complement() {

    // FILL IN THIS METHOD

    … }

    }

What would be the worst case running time (big O) of an implementation for a graph with n vertices and e edges?

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps11_sol.html

1/6

12/16/2016 CS112 Fall 2016: Problem Set 11

SOLUTION

public Graph complement() {
boolean[][] temp = new boolean[adjlists.length][adjlists.length]; // in temp, 􏰃ll in trues for the edges
for (int v=0;v < adjlists.length;v++) {

for (Edge e=adjlists[v];e != null;e = e.next) { temp[v][e.vnum] = true;

} }

// complement temp
for (int i=0; i < adjlists.length; i++) {

for (int j=0; j < adjlists.length; j++) { if (i != j) { // leave out the diagonal

temp[i][j] = !temp[i][j]; }

} }

// now create the adjacency linked lists for the complement graph Edge[] compall = new Edge[adjlists.length];
for (int v=0;v < compall.length;v++) {

for (int j=0; j < adjlists.length; j++) { if (temp[v][j]) {

Edge e = new Edge(); e.vnum = j;
e.next = compall[v]; compall[v] = e;

} }

}
// create new Graph and return Graph comp = new Graph(); comp.adjlists = compall;
return comp;

}

Running time is O(n^2) ‐ this is the time needed to compute the complement matrix. (A more abstract way of reasoning about this is to note that the original graph and its complement would involve all possible edges between the n vertices, which is O(n^2).)

3. WORK OUT THE SOLUTION TO THIS PROBLEM AND TURN IT IN AT RECITATION

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps11_sol.html

2/6

12/16/2016 CS112 Fall 2016: Problem Set 11

Consider this graph:

This graph has n+2 vertices and 2n edges. For every vertex labeled i, 1 <= i <= n, there is an edge from S to i, and an edge from i to T.

1. How many different depth‐first search sequences are possible if the start vertex is S? 2. How many different breadth‐first search sequences are possible if the start vertex is S?

SOLUTION
1. n!, for the different permutations of the vertices 1 through n. (Note: If a vertex v in this set is visited immediately after S, then T

would be immediately visited after v.)
For instance, say n = 3. Here are all possible DFS sequences (3! = 6):

S1T23 S1T32 S2T13 S2T31 S3T12 S3T21

2. n!, similar to DFS. The only difference is that T will be the last vertex to be visited. So, if n = 3, the possible BFS sequences are:

S123T S132T S213T S231T S312T S321T

4. * You can use DFS to check if there is a path from one vertex to another in a directed graph. Implement the method hasPath in the following. Use additional class fields/helper methods as needed:

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps11_sol.html

3/6

12/16/2016 CS112 Fall 2016: Problem Set 11

public class Neighbor { public int ve􏰂ex; public Neighbor next; …

}

public class Graph {
Neighbor[] adjLists; // adjacency linked lists for all ve􏰂ices

// returns true if there is a path from v to w, false otherwise public boolean hasPath(int v, int w) {

// FILL IN THIS METHOD

… }

}

SOLUTION

public boolean hasPath(int v, int w) { if (v == w) return false;
int n = adjlists.length;
boolean[] visited = new boolean[n]; for(inti=0;i<n;i++){

visited[i] = false; }

return pathDFS(v,w,visited); }

private boolean pathDFS(int current, int w, boolean[] visited) { if (current == w) return true;
visited[current] = true;
for (Neighbor ptr=adjlists[current]; ptr != null; ptr=ptr.next) {

if (!visited[ptr.ve􏰂ex]) {
if (pathDFS(ptr.ve􏰂ex, w, visited)) {

return true; }

} }

return false; }

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps11_sol.html

4/6

12/16/2016 CS112 Fall 2016: Problem Set 11

5. An undirected graph may be disconnected, if there are certain vertices that are unreachable from other vertices. In a disconnected graph, each island of vertices is called a connected component ‐ in each island, every vertex can reach all other vertices.

You are given the same Graph class as in problem #4, but this time it represents an undirected graph, and it does not have the hasPath method.

Implement a method in this class that will use dfs to number all connected components (0..), and return an array that holds, for each vertex, the number of the connected component to which it belongs. Implement helper methods as necessary. What is the big O running time of your implementation?

public class Graph {
Neighbor[] adjLists; // adjacency linked lists for all ve􏰂ices

// returns an array of connected component membership of ve􏰂ices,
// i.e. return[i] is the number of the connected number to which a ve􏰂ex belongs // connected components are numbered 0,1,2,…
public int[] connectedComponents() {

// FILL IN THIS IMPLEMENTATION }

… }

SOLUTION

// recursive dfs modi􏰃ed to deal out component number
private void dfs(int v, boolean[] visited, int[] compNums, int num) {

visited[v] = true;
compNums[v] = num;
for (Neighbor nbr=adjLists[i]; nbr != null; nbr=nbr.next) {

if (!visited[nbr.ve􏰂ex]) {
dfs(nbr.ve􏰂ex, visited, compNums, num);

} }

}
// returns an array of connected component membership of ve􏰂ices,

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps11_sol.html

5/6

12/16/2016 CS112 Fall 2016: Problem Set 11

// i.e. return[i] is the number of the connected number to which a ve􏰂ex belongs // connected components are numbered 0,1,2,…
public int[] connectedComponents() {

boolean[] visited = new boolean[adjLists.length]; int[] compNums = new int[adjLists.length];

for (int i=0,num=0; i < adjLists.length; i++,num++) { if (!visited[i]) {

dfs(i, visited, compNums, num); }

}

return compNums; }

The only addition to the basic dfs implementation is the assignment of a component number to a vertex immediately after it is marked as visited. This adds O(n) to the original running time of O(n+e)), which does not make a difference. In the connectedComponents method, there is a scan of the visited array, which takes O(n) time. Again this does not change the big O time. So the total running time is still O(n+e), same as basic dfs.

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps11_sol.html

6/6

12/16/2016 CS112 Fall 2016: Problem Set 12 Solution

Problem Set 12 ‐ Solution
Graphs: Topological Sorting, Traversal, Dijkstra’s Algorithm

1. You are given a directed graph:

class Neighbor {
public int ve􏰂ex; public Neighbor next; …

}

class Ve􏰂ex {
String name;
Neighbor neighbors; // adjacency linked lists for all ve􏰂ices

}

public class Graph { Ve􏰂ex[] ve􏰂ices;

// returns an array of indegrees of the ve􏰂ices, i.e. return[i] is the // number of edges that are directed IN TO ve􏰂ex i
public int[] indegrees() {

// FILL IN THIS METHOD

… }

… }

Assuming that the graph has already been read in, complete the indegrees method. SOLUTION

public int[] indegrees() {
int[] indeg = new int[ve􏰂ices.length]; for (int i=0; i < ve􏰂ices.length; i++) {

for (Neighbor nbr=ve􏰂ices[i].neighbors; nbr != null; nbr=nbr.next) { indeg[nbr.ve􏰂ex]++;

}

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps12_sol.html

1/6

12/16/2016 CS112 Fall 2016: Problem Set 12 Solution

}

return indeg; }

  1. What is the big O running time of your indegrees implementation if the graph has n vertices and e edges? Show your analysis. SOLUTION

    Accessing the front of a vertex’s neighbors list, updating the indegree of a vertex, and accessing the neighbor of a vertex are each unit time operations.
    There are e neighbors in all, for all vertices put together, so the neighbor access part contributes e units of time. Accessing the front of a vertex’s neighbors list is done n times in all, once per vertex. There are e indegree updates, one per edge.

    Total is e + n + e = n + 2e, which is O(n+e)

  2. With the same Graph class as in the previous example, assuming that the graph is acyclic, and that that the indegrees method has been implemented, implement a topso􏰂 method to toplogically sort the vertices using using BFS (breadth‐first search) (see algorithm in Section 14.4.4 of text):

    public class Graph { …

    public String[] indegrees() { … // already implemented

    }

    // returns an array with the names of ve􏰂ices in topological sequence public String[] topso􏰂() {

    // FILL IN THIS METHOD

    … }

    … }

    You may use the following Queue class:

    public class Queue<T> { …

    public Queue() {…}
    public void enqueue(T item) {…}
    public T dequeue() throws NoSuchElementException {…} public boolean isEmpty() {…}

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps12_sol.html

2/6

12/16/2016 CS112 Fall 2016: Problem Set 12 Solution

}

SOLUTION

// returns an array with the names of ve􏰂ices in topological sequence public String[] topso􏰂()
throws Exception {

// compute indegrees int[] indeg = indegrees();

int topnum=0;
String[] tops = new String[ve􏰂ices.length]; Queue queue = new Queue();

// 􏰃nd all ve􏰂ices with indegree zero, assign them topological numbers, and enqueue for (int i=0; i < indeg.length; i++) {

if (indeg[i] == 0) {
tops[topnum++] = ve􏰂ices[i].name; queue.enqueue(i);

} }

// loop until queue is empty while (!queue.isEmpty()) {

int v = queue.dequeue();
for (Neighbor nbr=ve􏰂ices[v].neighbors; nbr != null; nbr=nbr.next) {

indegrees[nbr.ve􏰂ex]–; if (indegrees[nbr] == 0) {

tops[topnum++] = ve􏰂ices[nbr.ve􏰂ex].name;

queue.enqueue(nbr.ve􏰂ex); }

} }

return tops; }

4. An undirected graph has n vertices and e edges, and is stored in adjacency linked lists. The edges DO NOT have weights. What would be the fastest algorithm (in the big O worst case sense) to find the shortest path from vertex numbered x to vertex numbered y, assuming y can

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps12_sol.html

3/6

12/16/2016 CS112 Fall 2016: Problem Set 12 Solution

be reached from x? Describe the algorithm, and state its big O worst case running time. SOLUTION

Algo:
Do a BFS starting at x. Set distance of x to 0. When an edge a–b is seen and b is enqueued, make distance of b equal to distance of a plus

1. When y is reached, stop.
Worst case running time is O(n+e) since in the worst case, we would need to run BFS over the entire graph (i.e. y is the last vertex seen),

and the running time of BFS is O(n+e).

5. A strongly connected directed graph is one in which every vertex can reach all other vertices. In the following Graph class, implement a method stronglyConnected that returns true if the graph is strongly connected, and false otherwise. What is the worst case big O running time of your implementation?

public class Graph { Ve􏰂ex[] ve􏰂ices;

// pe􏰆orms a recursive dfs sta􏰂ing at ve􏰂ex v private void dfs(int v, boolean[] visited) {

// already implemented …

}

public boolean stronglyConnected() { // FILL IN THIS IMPLEMENTATION

}

… }

SOLUTION

public boolean stronglyConnected() {
boolean[] visited = new boolean[ve􏰂ices.length]; for (int i=0; i < ve􏰂ices.length; i++) {

for (int j=0; j < visited.length; j++) { visited[i] = false;

}
dfs(i, visited);

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps12_sol.html

4/6

12/16/2016 CS112 Fall 2016: Problem Set 12 Solution

for (int j=0; j < visited.length; j++) { if (!visited[j]) {

return false; }

} }

return true; }

In the worst case, every vertex can reach all other vertices. The dfs method is called once for each vertex, and the time for a dfs run is

O(n+e). So the total time is n*O(n+e) = O(n2+ne). (Note: since e can be anywhere between 0 and O(n2), we cannot simplify the big O result any further.

6. Suppose you are given this undirected graph in which the vertices are towns, and the edges are toll roads between them. The weight of an edge is the dollar amount of toll.

Use Dijsktra’s shortest paths algorithm to determine the minimum toll route from A to all other cities. Show each step of the algorithm in tabular form. Here’s the table after the initial step:

Done D[B] D[C] D[D] D[E] D[F] D[G] D[H] D[I] ———————————————————————

A 4,A ∞ ∞ ∞ ∞ ∞ 8,A ∞

Note that along with the distance, the “previous” vertex is also shown.

Draw the shortest path tree induced on the graph. SOLUTION

Done D[B] D[C] D[D] D[E] D[F] D[G] D[H] D[I] ———————————————————————

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps12_sol.html

5/6

12/16/2016 CS112 Fall 2016: Problem Set 12 Solution

A 4,A ∞ ∞ ∞ ∞ ∞ 8,A ∞ B 12,B ∞ ∞ ∞ ∞ 8,A ∞

H G F C I D E

12,B ∞ ∞ ∞ 9,H 15,H 12,B ∞ ∞ 11,G 15,H

12,B 25,F 21,F 19,C 21,F

19,C 21,F 21,F

15,H 14,C

Note that along with the distance, the “previous” vertex is also shown. The shortest path tree induced on the graph:

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps12_sol.html

6/6

12/16/2016 CS112 Fall 2016: Problem Set 13 Solution

Problem Set 13 ‐ Solution Sorting

1. Trace the mergesort algorithm on the following list:

3,26,67,25,9,-6,43,82,10,54

Show the resulting recursion tree, with the to‐be‐sorted original and sub‐lists at each node, and the number comparions for each merge. (Assume that if there is an odd number of entries in an array, the left part has one more entry than the right after the split.)

SOLUTION
The original and sorted result indicated above and below:

-6,3,9,10,25,24,43,54,67,84 #c9

3, 26, 67,25, 9,-6,43,82,10,54 /\

/\
/ 3,9,25,26,67 #c3 \ -6,10,43,54,82 #c4

3,26,67,25,9 -6,43,82,10,54 /\/\

/\/\
/ 3,26,67 #c2 \ 9,25 #c1 / -6,43,82 #c2 \ 10,54 #c1

3,26,67 25,9 -6,43,82 10,54 /\/\/\/\

/3,26#c1 \67 /9 \25 /-6,43#c1 \82 /10 \54 3,26 67 9 25-6,43 82 10 54
/\ /\

/3 \6 /-6\43 3 26 -6 43

2. Mergesort works well on linked lists since it doesn’t need any extra space. Given the following linked list node class:

public class LLNode<T extends Comparable<T>> { public T info;
public LLNode<T> next;

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps13_sol.html

1/6

12/16/2016 CS112 Fall 2016: Problem Set 13 Solution

}

complete the following method to “split” the linked list in half:

// splits the given list in half such that the return value is
// a reference to the 􏰃rst node of the second half. Also, the
// “next” 􏰃eld of the last node in the 􏰃rst half is set to null.
static <T extends Comparable<T> LLNode<T> split(LLNode<T> list) {

// COMPLETE THIS METHOD }

SOLUTION

static <T extends Comparable<T> LLNode<T> split(LLNode<T> list) { if (list == null) return null;

int size=0;
LLNode<T> ptr;
for (ptr=list; ptr != null; ptr = ptr.next) {

size++; }

size = (size+1)/2; ptr=list; while (size > 1) {

ptr = ptr.next;

size–; }

LLNode<T> second = ptr.next; ptr.next = null;
return second;

}

3. In Problem Set 2, #5, you saw how to find the common elements in two sorted linked lists of integers. Here is the header of a modified version of that method, that merges instead of finding common elements, and will work on lists of Comparable objects (not just ints). Complete this method

using recursion. Your method should recycle the nodes in the original lists (no new nodes should be created).

// merge the lists l1 and l2 into a single linked list, whose
// 􏰃rst node is referenced by the return value – no additional
// linked list nodes are used
static <T extends Comparable<T>> LLNode<T> merge(LLNode<T> l1, LLNode<T> l2) {

// COMPLETE METHOD USING RECURSION, NO NEW NODES TO BE CREATED }

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps13_sol.html

2/6

12/16/2016 CS112 Fall 2016: Problem Set 13 Solution

Using this merge solution, and the solution to the split in the previous problem, complete the mergesort implementation:

// So􏰂s the input linked list using mergeso􏰂, and returns the front of
// the so􏰂ed linked list. DOES NOT CREATE ANY ADDITIONAL NODES. public static <T extends Comparable<T>
LLNode<T> mergeso􏰂(LLNode<T> list) {

// COMPLETE THIS METHOD }

SOLUTION

// merge the lists l1 and l2 into a single linked list, whose
// 􏰃rst node is referenced by the return value – no additional
// linked list nodes are used
static <T extends Comparable<T>> LLNode<T> merge(LLNode<T> l1, LLNode<T> l2) {

// COMPLETE METHOD USING RECURSION, NO NEW NODES TO BE CREATED if (l1 == null) { return l2; }
if (l2 == null) { return l1; }
if (l1.info.compareTo(l2.info) < 0) {

l1.next = merge(l1.next, l2);

return l1; }else{

l2.next = merge(l1, l2.next);

return l2; }

}

public static <T extends Comparable<T> LLNode<T> mergeso􏰂(LLNode<T> list) {

// empty or single node list
if (list == null || list.next == null) {

return list; }

//split
LLNode<T> second = split(list);

// recursive calls
list = mergeso􏰂(list);
second = mergeso􏰂(second);

// merge

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps13_sol.html

3/6

12/16/2016 CS112 Fall 2016: Problem Set 13 Solution

return merge(􏰃rst, second); }

4. Trace the quicksort algorithm on the following array:

3,26,67,25,9,-6,43,82,10,54

Use the median of the first, middle, and last entries as the pivot to split a subarray. (If a subarray has fewer than 3 entries, use the first as the pivot.) Show the quicksort tree and the number of comparisons at each split. SOLUTION

[3 26 67 25 9 -6 43 82 10 54] median(3,9,54)=9, swap(9,3) split

[3 -6] split

9

[25 67 26 43 82 10 54] split

| piv=43,#c = 6

| piv=3,#c = 1

|pivot=9,#ofcomp=9 V

VV
[-6]3 [251026] 43 [826754]

split split
| piv=25,#c=2 | piv=67,#c=2 VV

[10] 25 [26] [54] 67 [82]

Total number of comparisons = 20 5. Given the following input array:

3,26,67,25,9,-6,43,82,10,54

  1. Trace the linear time build‐heap algorithm on this array, to build a max‐heap. How many comparisons did it take to build the heap?
  2. Starting with this max‐heap, show how the array is then sorted by repeatedly moving the maximum entry to the end and applying sift‐down

    to restore the (remaining) heap. How many comparisons did it take to sort the heap?

SOLUTION

1. Array Si􏰄 Down Comparisons ——————————————— ——— ———– 3 26 67 25 9 -6 43 82 10 54 9 1

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps13_sol.html

4/6

12/16/2016 CS112 Fall 2016: Problem Set 13 Solution

2.

326672554-64382109 252 326678254-64325109 672 326678254-64325109 264 382672654-64325109 35 825467269-64325103 done

Array Si􏰄 Down Comparisons ——————————————— ——— ———– 82 54 67 26 9 -6 43 25 10 3

swap(82,3) 35467269-643251082 34

67 54 43 26 9 -6 3 25 10 82 swap(67,10)

105443269-63256782 106

54 26 43 25 9 -6 3 10 67 82 swap(54,10)

102643259-63546782 104

43 26 10 25 9 -6 3 54 67 82 swap(43,3)

32610259-643546782 34

26 25 10 3 9 -6 43 54 67 82 swap(26,-6)

-62510392643546782 -64

25 9 10 3 -6 26 43 54 67 82 swap(25,-6)

-69103252643546782 -62

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps13_sol.html

5/6

12/16/2016 CS112 Fall 2016: Problem Set 13 Solution

10 9 -6 3 25 26 43 54 67 82 swap(10,3)

39-610252643546782

9 3 -6 10 25 26 43 54 67 82 swap(9,-6)

-63910252643546782

3 -6 9 10 25 26 43 54 67 82 swap(3,-6)

-63910252643546782

32

-6 1

done

6. A stable sorting algorithm is one which preserves the order of duplicate elements when sorted. For instance, suppose the following pairs of values are sorted on the first value in the pair:

(3,sun) (2,mars) (4,moon) (3,venus)

then the output of a stable sorting algorithm would be:

(2,mars) (3,sun) (3,venus) (4,moon)

Notice that (3,sun) comes before (3,venus), preserving the order of the input for elements that have the same sortable value of 3, hence stable. However, if the output is this:

(2,mars) (3,venus) (3,sun) (4,moon)

then the sorting algorithm is not stable since it does not preserve the input order of (3,sun) before (3,venus).

For each of insertion sort, mergesort, and quicksort, tell whether the algorithm is stable or not. SOLUTION

Insertion sort is a stable sort. Mergesort is a stable sort. Quicksort is not a stable sort.

https://www.cs.rutgers.edu/courses/112/classes/fall_2016_venugopal/probs/ps13_sol.html

6/6