220 likes | 337 Views
CS252: Systems Programming. Ninghui Li Program Interview Questions. String Problem.
E N D
CS252: Systems Programming Ninghui Li Program Interview Questions
String Problem • Input is a string containing a set of words separated by white space(s). Write a function that will transform it to a string in which the words appear in the reverse order. For example "this is really good" becomes "good really is this". • We require that only a constant amount of extra space, and linear time is used.
String Problem Solution • Solution: two-pass processing • First pass reverse whole string • Second pass, find each word and reverse it locally
Similar Problem • Consider strings over alphabet {a,b,c,d}, write a function that takes an input string, and (1) removes each “b”, (2) replaces each “a” by “dd”, and does so in place (assume the string is in a buffer long enough for the result) using constant additional storage.
Linked List: Deletion from a Singly Linked List • Given a singly linked list, you are given one node and are asked to delete it from the list. • You are asked to do it in constant time. • What is the challenge? • This is possible when the node is not the last node in the list, and copying the data field in the node takes constant time. • How?
Linked List: Checking for Cyclicity • Although a linked list is supposed to end with NULL, it is possible to have it points to another element in the list, creating a cycle • Write code to check whether a singly linked list ends in NULL or contains a cycle • C1: no modifying the list. • C2: constant extra space. • C3: linear time running time • How to find the first element of the cycle?
Linked List: Checking for Cyclicity • Solution 1: Satisfies C2, C3; violate C1; • Remember the head, reverse the linked list as one traverses it, and report cycle if one reaches the head node again. • Solution 2: Satisfies C2, C3; violates C1; assumes that there is a bit in the data structure that is initialized to 0
Linked List: Checking for Cyclicity • Solution 3: Satisfies C1, C3; violate C2; • Record all visiting nodes in a hash table, and do a lookup for each newly encountered node. • Solution 4: Satisfies C1, C2; violates C3; • For each newly encountered node, check whether its next will be visited if one starts from head again and try to traverse to current node.
Linked List: Checking for Cyclicity • Solution 5: Satisfies C1, C2, C3; • Uses 2 pointers. One fast and one slow. Fast one advances two steps each time, and show one advances one step each time, they meet if and only if there is a cycle. • To figure out where cycle starts, • First figure out cycle length X, and pinning fast pointer, and count how many steps it takes slow pointer to meet fast • Then set fast pointer at position X, and slow at beginning, advance both at 1 step at a time, when they meet, slow is pointing at beginning of cycle
Additional LinkedList Problem • How to find the middle of a linked list in one pass of the linked list?
Tower of Hanoi • Move n rings stacked on Peg 1 (rings are from small to large from top to bottom) to Peg 2, • Peg 3 is empty. • Write a program to output the necessary steps to move n rings on Peg 1 to Peg 2.
Implementing a Queue with two Stacks • Queue (FIFO) supports two operation • enqueue (add an element) • dequeue (remove the first added element) • Stack (LIFO) supports two operations • push (add an element) • pop (remove the last added element) • How to implement a queue using two stacks?
Implementing a Queue with two Stacks • Enqueue(e) { • stack1.push(e); • } • Dequeue(){ • if (stack2.isEmpty()) { • while(! stack1.isEmpty()) { • stack2.push(stack1.pop()); • } • return stack2.pop(); • }
Implement a Reentrant (or Recursive) Lock • If a thread currently holding the lock tries to lock it again, for a non-reentrant or non-recursive lock, we have a deadlock • A reentrant (or recursive) lock allows the thread to proceed; the thread must unlock it correct number of times for other process to obtain the lock
Big Data with Limited Memory • Given an input file with four billion non-negative integers, provide an algorithm to generate an integer which is not contained in the file. Assume you have 1GB of memory available for this task. • Use a bit vector, each bit to represent whether an integer is present; this requires 2^31 bit, or about 256M bytes. Taken from Gayle Laakmann McDowell: “Cracking the Coding Interview”, 5th Edition.
Big Data with Memory Limit (continued) • What if you have only 10MB of memory? Assume that for input you have no more than one billion non-negative integers, and they are all distinct. • First scan determines # of integers in each thousands, e.g., between 0 and 1023, 1024 and 2047, etc. • Find a region that is not full, second scan finds a number in that region • What if the integers are not guaranteed to be distinct? Taken from Gayle Laakmann McDowell: “Cracking the Coding Interview”, 5th Edition.
Hash Table • How to design a hash function for words in a dictionary, e.g., for use in a hash table of size N? • What makes a good hash function? • Distribution of output is close of uniform over [0..N-1]. • Is sum of all characters a good hash function? • Is product of all characters a good hash function?
Anagrams • Two words are anagrams if they contain the same set of characters. • Write a program to partition a dictionary into sets of words such that all words in each set are anagrams.
Divide and Conquer • Recursively • Divide: break down the problem into two or more sub problems: • Conquer: solve the sub problems, and then combine their results • Example: Merge sort
Divide and Conquer Question • Compute the number of reversed pairs in an array A of numbers. A pair (i,j) is reversed if A[i]>A[j]. • Solution idea (do merge sort while computing this): • # of inverse in whole = # of inverse in left half • + # of inverse in right half • + # of inverse involving one element in left and one in right (can be computed while merging left and right) • Code available • https://github.com/adnanaziz/EpiCode/blob/master/Java/com/epi/CountInversions.java
Divide and Conquer Question • Diameter of a tree • Consider a tree where each edge has a number (distance), compute the maximal distance between two leaf nodes. • Solution Idea: • For each internal node, computes the max distance as well as the max height
Pseudo Code • max_dist(node *p, &dt, &ht) { // dt:distance, ht:height • intcd, ch, ht2=0, nht; // ht2 stores second highest height • *dt=0; *ht=0; • if (p is leaf) return; • for each child c of p { • max_dist(c, &cd, &ch); • if (cd>*dt) *dt=cd; // current max distance is from subtree at c • nht = ch + e(c); // e(c) is distance on the edge to child c • if (nht > *ht) { ht2 = *ht; *ht= nht;} • else if (nht > ht2) { ht2 = nht; } • if (ht2>0 && *ht+ht2>*dt) { *dt= *ht+ht2; } • // current max distance from leafs in two subtrees • } • }