final exam - web.stanford.edu€¦ · a k-ordered statistic tree is a binary search tree where each...

16
CS106B Autumn 2017 Instructor: Cynthia Lee December 11, 2017 FINAL EXAM NAME (LAST, FIRST): _____________________________________________________ SUNET ID: ________________________________________________ @stanford.edu 1 2 3 4 5 Exam extras TOTAL Heap Inheritance Recursive Backtracking Graphs Trees 18 10 18 16 26 2 90 Instructions: The time for this exam is 3 hours. Use of anything other than a pencil, eraser, pen, one 8.5x11 page (both sides) of notes, and the official textbook is prohibited. In particular, no computers or digital devices of any kind are permitted. For scratch paper, please just use the blank back sides of each exam page. If part of your solution is on the back of a page, you MUST clearly indicate this in the space where the answer was supposed to go. Write your name on each page on the line provided (worth 1pt). You must do this during the exam— writing your name after time is called will not be permitted. PLEASE tear off the pages of library reference in the back of the exam and do not turn them in (also 1 pt). Please sign before you begin: I agree to abide by the spirit and letter of the Honor Code, and to follow the instructions above. _______________________________________________ ______________ ______________________ (Signature) (Date) (Start time - HH:MM zone)

Upload: others

Post on 12-Apr-2020

4 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: FINAL EXAM - web.stanford.edu€¦ · A k-ordered statistic tree is a Binary Search Tree where each node has an additional field that stores the number of nodes in its left subtree

CS106B

Autumn 2017

Instructor: Cynthia Lee

December 11, 2017

FINAL EXAM

NAME (LAST, FIRST): _____________________________________________________

SUNET ID: ________________________________________________ @stanford.edu

1 2 3 4 5

Exam extras

TOTAL Heap Inheritance

Recursive

Backtracking

Graphs Trees

18 10 18 16 26 2 90

Instructions:

The time for this exam is 3 hours.

Use of anything other than a pencil, eraser, pen, one 8.5x11 page (both sides) of notes, and the official

textbook is prohibited. In particular, no computers or digital devices of any kind are permitted. For scratch

paper, please just use the blank back sides of each exam page. If part of your solution is on the back of a

page, you MUST clearly indicate this in the space where the answer was supposed to go.

Write your name on each page on the line provided (worth 1pt). You must do this during the exam—

writing your name after time is called will not be permitted.

PLEASE tear off the pages of library reference in the back of the exam and do not turn them in (also 1 pt).

Please sign before you begin:

I agree to abide by the spirit and letter of the Honor Code, and to follow the instructions above.

_______________________________________________ ______________ ______________________

(Signature) (Date) (Start time - HH:MM zone)

Page 2: FINAL EXAM - web.stanford.edu€¦ · A k-ordered statistic tree is a Binary Search Tree where each node has an additional field that stores the number of nodes in its left subtree

1. Heap (18pts). We have implemented the Priority Queue ADT using a binary min-heap.

(a) (10pts) Draw a diagram of the tree shape of the heap after enqueuing the following priorities in the order

given. 15, 10, 13, 8, 2, 9 (for this priority queue we don’t have a separate value, just the priority).

Diagram after inserting 15: This one is completed for you as a node formatting example.

Diagram after inserting 10:

Diagram after inserting 13:

Diagram after inserting 8:

Diagram after inserting 2: Diagram after inserting 9:

15

Page 3: FINAL EXAM - web.stanford.edu€¦ · A k-ordered statistic tree is a Binary Search Tree where each node has an additional field that stores the number of nodes in its left subtree

(b) (4pts) Continuing from the final heap in part (a) (after inserting 9), draw a diagram of the tree shape of

the heap after calling dequeue twice.

Diagram after calling dequeue once: Diagram after calling dequeue a second time:

(c) (4pts) Draw the array version of the heap after the second dequeue above, including the capacity and size

fields, as discussed in class. Leave currently unused parts of the array blank.

Array index

0 1 2 3 4 5 6 7 8 9

Array contents

Capacity:

Size:

Page 4: FINAL EXAM - web.stanford.edu€¦ · A k-ordered statistic tree is a Binary Search Tree where each node has an additional field that stores the number of nodes in its left subtree

2. Inheritance (10pts). Consider the classes on the left; assume that each is defined in its own file.

class Anakin { public: virtual void m1() { cout << "A 1" << endl; } void m3() { cout << "A 3" << endl; m1(); } }; class Leia : public Anakin { public: virtual void m2() { cout << "L 2" << endl; Anakin::m3(); } void m3() { cout << "L 3" << endl; m1(); } }; class Kylo : public Leia { public: virtual void m1() { cout << "K 1" << endl; } virtual void m2() { cout << "K 2" << endl; Leia::m3(); } void m3() { cout << "K 3" << endl; m2(); } }; Now assume that the following variables are defined: Anakin* var1 = new Leia(); Anakin* var2 = new Kylo(); Leia* var3 = new Kylo();

In the table below, indicate in the right-hand column the output produced by the statement in the left-hand column. If the statement produces more than one line of output, indicate the line breaks with slashes as in "x / y / z" to indicate three lines of output with "x" followed by "y" followed by "z".

If the statement does not compile, write "compiler error". If a statement would crash at runtime or cause unpredictable behavior, write "crash".

Statement

var1->m1();

var1->m3();

var2->m1();

var2->m2();

var3->m2();

((Kylo*) var1)->m3();

((Leia*) var2)->m2();

((Kylo*) var2)->m1();

((Kylo*) var3)->m3();

((Anakin*) var3)->m1();

Output (1pt each)

Page 5: FINAL EXAM - web.stanford.edu€¦ · A k-ordered statistic tree is a Binary Search Tree where each node has an additional field that stores the number of nodes in its left subtree

3. Recursive Backtracking (18pts). The game of Battleship is a time-honored

competition amongst friends. Each person has a board (which we’ll represent with

a Grid) where they secretly place several “ships” (1xN rectangles) so that they do

not overlap other ships or go off the board. The picture to the right is an example

of a Grid with 4 ships placed on it: size 3 (placed horizontally), size 2 (placed

vertically), and two of size 1. Each cell with ‘B’ represents part of a ship, and

complete ships are outlined in black.

To win, you try to “sink” your friend’s ship by naming a row/col location to target with a cannon. Your friend

self-reports whether you “hit” on a part of one of their ships or not (“miss”). If the locations you name result

in many consecutive misses, you might begin to wonder whether your opponent is cheating in their self-

reporting! So you decide to write a backtracking recursion program to determine whether there’s any legal

way to place the ships that avoids all the locations you’ve targeted so far.

(a) (6pts) First, you’ll need a helper function placeHoriz that attempts to place one

ship on the board in a specified location. We represent your friend’s board (from

your perspective) as a Grid<char>, where ‘?’ represents a spot you know nothing

about, ‘M’ represents a location you have already targeted (and that your friend

said was a miss), and ‘B’ represents a placed ship (placed tentatively as part of

backtracking exploration). The function takes the current Grid, the length of the

ship, and a row-col where you should place the ship. As the function’s name

suggests, you should try to place the ship horizontally on the board with the

leftmost part of the ship at row and col. If the ship fits (does not overlap any ‘M’ or

‘B’ cells, and stays in bounds of the board), fill in the designated cells with ‘B’ (to

indicate a tentative guess at a possible ship placement) and return true. Otherwise

return false. If your function returns false, no changes should be made to the board.

bool placeHoriz (Grid<char>& board, int size, int row, int col){

}

Before:

After (with size=2,

row=2, col=1):

Page 6: FINAL EXAM - web.stanford.edu€¦ · A k-ordered statistic tree is a Binary Search Tree where each node has an additional field that stores the number of nodes in its left subtree

(b) (12pts) Now write a recursive backtracking function canPlaceShips that checks if a collection of ships

can all be placed on the board such that they do not overlap each other or any cell marked ‘M.’ The

collection of ships is provided as a Vector<int> of sizes, where each int represents one ship’s size. The

function returns true if it’s possible to place all the ships on the board, and false otherwise.

Example: It would be impossible to place four ships of sizes 3, 2, 1, and 1 in any configuration on

the “before” example board in part (a)—something fishy (ha) is going on with your friend’s self-

reporting!—so you would return false in that case.

You’ll want to use your placeHoriz helper function, and you may assume a corresponding

placeVert also exists, which does the same except that it places the ship vertically.

You may also assume you have helpers and unplaceHoriz and unplaceVert, which remove a

ship of size size from the specified location by writing ‘?’ in all its cells (the ‘unplace’ functions

have the same input parameter list as the ‘place’ functions, but void return type).

Your function should use backtracking recursion. Your code is not required to have any particular

Big-O cost, but you may lose points if your code is extremely inefficient, such as exploring

obviously invalid paths rather than stopping and backtracking.

bool canPlaceShips(Grid<char>& board, Vector<int> shipSizes){

}

Page 7: FINAL EXAM - web.stanford.edu€¦ · A k-ordered statistic tree is a Binary Search Tree where each node has an additional field that stores the number of nodes in its left subtree

4. Graphs (16pts). Noticing the popularity of the Stanford Marriage Pact, Stanford’s housing office has decided

to use a similar algorithm to match roommates next year. They want to force students currently in Roble and

Wilbur to mix next year, so each roommate pair must include one student from each. Based on a proprietary

deep learning algorithm that examines your social media and grades (serious privacy issues in this

hypothetical!), ResEd has created a weighted, directed graph of all students in R[oble] and W[ilbur], where an

edge exists from each student in R to each student in W, with weight indicating how much the R student

should want to match with the W student. Corresponding reverse edges (with potentially different weights)

exist from W students to R students. Note that smaller weights indicate more desirable matches, and R and

W have the same number of students. You will write a function to help ResEd create roommate matches!

(a) (5pts) Before we tackle the main algorithm, write a helper function that takes a BasicGraph of the

roommate ratings and returns a Map from W students (vertices colored WHITE) to a PriorityQueue of

R students (vertices colored RED), where the priority is the weight of the edge from the W student to that

R student. (Assume ints WHTIE and RED are already defined appropriately as constants.)

Map<Vertex*, PriorityQueue<Vertex*>> getWPrefs(BasicGraph& graph) {

}

Page 8: FINAL EXAM - web.stanford.edu€¦ · A k-ordered statistic tree is a Binary Search Tree where each node has an additional field that stores the number of nodes in its left subtree

(b) (11pts) Now we will write the main algorithm:

Some of this code is written for you (see next page).

Variable wPrefs is the return value of your helper in (a), isMatched tracks which W students already

have matches, and matches map each R student to their current W student match.

The algorithm repeats the following actions in a loop until all students have a match:

Loop over wPrefs keys and, for each W student that is not already matched, attempt to match them

with the next highest-priority roommate for them (next in W’s PriorityQueue):

o A match attempt will succeed if the R student is currently not matched to anyone.

o A match attempt will also succeed if the R student is currently matched to someone else, but the

R student would prefer this new W student to their current match (i.e., the new edge weight is less

than the edge weight with the current match).

o To perform a match, update isMatched and matches accordingly, including breaking the

previous match if the R student had one.

o If the first match attempt for W fails, W stays unmatched this round. Continue the loop to the next

W student in wPrefs.

Return matches.

Please write your code on the next page.

Page 9: FINAL EXAM - web.stanford.edu€¦ · A k-ordered statistic tree is a Binary Search Tree where each node has an additional field that stores the number of nodes in its left subtree

Map<Vertex*, Vertex*> matchRoommates(BasicGraph& graph) {

Map<Vertex*, PriorityQueue<Vertex*>> wPrefs = getWPrefs(graph); // W -> PQ<R>

Set<Vertex*> isMatched; // W vertices that are currently matched

Map<Vertex*, Vertex*> matches; // from R to W

while (isMatched.size() < wPrefs.size()) {

for (Vertex* w : wPrefs) {

} } return matches; }

Page 10: FINAL EXAM - web.stanford.edu€¦ · A k-ordered statistic tree is a Binary Search Tree where each node has an additional field that stores the number of nodes in its left subtree

(b) Trees (26pts). A k-ordered statistic tree is a Binary Search Tree where each node has an additional field

that stores the number of nodes in its left subtree. The k-ordered statistic tree can use this information

to quickly locate the kth element in the tree (kth if all elements were listed in ascending sorted order). We

will use this to implement a Set ADT, so keys in the tree are all unique.

Example: Below is a valid k-ordered statistic tree. Notice the keys follow the usual BST ordering.

The file korder.h is as follows (do not edit this code):

struct Node { Node(int key) { this->key = key; count = 0; left = right = NULL; } int key; // the usual BST key

int count; // count of nodes in left subtree Node* left; // left child Node* right; // right child

}; class KTree { public: KTree(); ~KTree(); void addKey(int key); int getKthKey(int k); private:

Node* root; };

Page 11: FINAL EXAM - web.stanford.edu€¦ · A k-ordered statistic tree is a Binary Search Tree where each node has an additional field that stores the number of nodes in its left subtree

Functions in the korder.cpp file are shown below and on the following 2 pages. Complete the code for them. You are welcome to add additional helper function(s) if you want (do not add them to the class in .h file, just add them below).

// (2pts) Constructor KTree::KTree()

{

}

// (6pts) Destructor KTree::~KTree()

{

}

Page 12: FINAL EXAM - web.stanford.edu€¦ · A k-ordered statistic tree is a Binary Search Tree where each node has an additional field that stores the number of nodes in its left subtree

// (7pts) Inserts key into the tree in the proper place, and updates all tree // counts appropriately. Your solution must be recursive, using the provided // helper. void KTree::addKey(int key) {

}

// Recursive helper function for addKey. Returns true if node was added, false // if key was duplicate so no add was done. The code for a standard BST insert // is already provided here for you. You should edit this code to make it // work for k-ordered tree. Write your additional line(s) of code to the right // and use arrows to indicate where to insert your addition(s). Cross out any // code you want to delete. bool addKeyHelper(int key, Node* curr)

{

if (key < curr->key) {

if (curr->left == NULL) {

curr->left = new Node(key);

return true;

} else {

return addKeyHelper(curr->left);

}

} else if (key > curr->key) {

if (curr->right == NULL) {

curr->right = new Node(key);

return true;

} else {

return addKeyHelper(curr->right);

}

} else {

return false;

}

}

Page 13: FINAL EXAM - web.stanford.edu€¦ · A k-ordered statistic tree is a Binary Search Tree where each node has an additional field that stores the number of nodes in its left subtree

// (11pts) Returns the kth smallest key in the tree (numbered starting // with 0). In the example tree above, for k=0 return 2; k=3 return 11; k=5 // return 20. You may assume that is valid (0 <= k < N for tree with N nodes). // Your solution must be recursive (see recursive helper below). For full // credit, your solution must be O(logN). As a fallback option, O(N) solutions // that do not use auxiliary data structures will incur a small 2pt deduction. int KTree::getKthKey(int k)

{

}

// Recursive helper for getKthKey(). For the O(N) solution, you may add

// argument(s) and change the return value if you like. For the O(logN)

// solution, this is the best header.

int kthKeyHelper(int k, Node* curr )

{

}

Page 14: FINAL EXAM - web.stanford.edu€¦ · A k-ordered statistic tree is a Binary Search Tree where each node has an additional field that stores the number of nodes in its left subtree

Summary of Relevant Data Types

We tried to include the most relevant member functions for the exam, but not all member functions are listed.

You are free to use ones not listed here that you know exist. You do not need #include.

class string {

bool empty() const; // O(1)

int size() const; // O(1)

int find(char ch) const; // O(N)

int find(char ch, int start) const; // O(N)

string substr(int start) const; // O(N)

string substr(int start, int length) const; // O(N)

char& operator[](int index); // O(1)

const char& operator[](int index) const; // O(1)

};

class Vector {

bool isEmpty() const; // O(1)

int size() const; // O(1)

void add(const Type& elem); // operator+= used similarly – O(1)

void insert(int pos, const Type& elem); // O(N)

void remove(int pos); // O(N)

Type& operator[](int pos); // O(1)

};

class Grid {

int numRows() const; // O(1)

int numCols() const; // O(1)

bool inBounds(int row, int col) const; // O(1)

Type get(int row, int col) const; // cascade of operator[] also works – O(1)

void set(int row, int col, const Type& elem); // O(1)

};

class Stack {

bool isEmpty() const; // O(1)

void push(const Type& elem); // O(1)

Type pop(); // O(1)

};

class PriorityQueue {

void changePriority(ValueType value, double newPriority);

void clear();

ValueType dequeue();

void enqueue(const ValueType& value, double priority); ValueType peek() const;

int size() const;

};

Page 15: FINAL EXAM - web.stanford.edu€¦ · A k-ordered statistic tree is a Binary Search Tree where each node has an additional field that stores the number of nodes in its left subtree

class Queue {

bool isEmpty() const; // O(1)

void enqueue(const Type& elem); // O(1) Type dequeue(); // O(1)

};

class Map {

bool isEmpty() const; // O(1)

int size() const; // O(1) void put(const Key& key, const Value& value); // O(logN)

bool containsKey(const Key& key) const; // O(logN)

Value get(const Key& key) const; // O(logN)

Value& operator[](const Key& key); // O(logN)

};

Example for loop: for (Key key : mymap){…}

class HashMap {

bool isEmpty() const; // O(1)

int size() const; // O(1)

void put(const Key& key, const Value& value); // O(1)

bool containsKey(const Key& key) const; // O(1) Value get(const Key& key) const; // O(1)

Value& operator[](const Key& key); // O(1)

};

Example for loop: for (Key key : mymap){…}

class Set {

bool isEmpty() const; // O(1)

int size() const; // O(1)

void add(const Type& elem); // operator+= also adds elements – O(logN)

bool contains(const Type& elem) const; // O(logN)

void remove(ValueType value);

}; Example for loop: for (Type elem : mymap){…}

class Lexicon { int size() const; // O(1) bool isEmpty() const; // O(1) void clear(); // O(N) void add(string word); // O(W) where W is word.length() bool contains(string word) const; // O(W) where W is word.length() bool containsPrefix(string pre) const; // O(W) where W is pre.length() };

Example for loop: for (string str : english){…}

Page 16: FINAL EXAM - web.stanford.edu€¦ · A k-ordered statistic tree is a Binary Search Tree where each node has an additional field that stores the number of nodes in its left subtree

struct Edge {

Vertex* start;

Vertex* finish; double weight;

bool visited;

};

struct Vertex {

string name; Set<Edge*> arcs;

Set<Edge*>& edges;

bool visited;

Vertex* previous;

int getColor();

};

class BasicGraph : public Graph<Vertex, Edge> {

public:

Vertex* addVertex(Vertex* v);

Edge* getEdge(Vertex* v1, Vertex* v2) const;

Edge* getEdge(string v1, string v2) const; const Set<Edge*>& getEdgeSet() const;

const Set<Edge*>& getEdgeSet(Vertex* v) const;

const Set<Edge*>& getEdgeSet(string v) const;

const Set<Vertex*> getNeighbors(Vertex* vertex) const;

const Set<Vertex*> getNeighbors(string vertex) const;

Vertex* getVertex(string name) const;

const Set<Vertex*>& getVertexSet() const;

void removeEdge(string v1, string v2, bool directed = true);

void removeEdge(Vertex* v1, Vertex* v2, bool directed = true);

void removeEdge(Edge* e, bool directed = true);

void removeVertex(string name);

void removeVertex(Vertex* v); void resetData();

}