Normally, there would be 3 rounds interviews. First round has two questions, first question normally is easy and then the next one could be a bit difficult. Then the second round would be one median level problem and a system / OO design question, or only system / OO design. Final round is either difficult problem or a system / OO design.
Afternoon interviews would be behaviour questions mixed up with the coding, system design and brain teaser problems. I believe the goal of the afternoon interviews would be the decision from team manager, who want to know that you can be the good fit to the team, like solving problems together, discussion and etc.
This document references the posts in 1point3acres and the following docs. Thank you guys.
Add, Subtract, Multiply, Divideๅไธชclass็ปงๆฟ่ฟไธชOperator base class็ๅๆณ
pay attention to Divide
C++ code was copied from somewhere else.
Java code was created based the c++ code, and it works.
Design Pattern
* Factory Pattern
packagequestions;// Calculatorimportjava.util.*;abstractclassToken<T> {publicToken() {}abstractbooleanisOperator();abstractvoidprocess(Stack<T> stack) throwsException;}classOperand<T> extendsToken<T> {privatefinalT value;publicOperand(finalT operand) {this.value= operand; }publicTgetValue() {returnthis.value; }publicbooleanisOperator() {returnfalse; }publicvoidprocess(finalStack<T> stack) {stack.push(this.value); }}abstractclassOperator<T> extendsToken<T> {privatefinalString type;publicOperator(finalString type) {this.type= type; }publicStringtype() {returnthis.type; }publicbooleanisOperator() {returntrue; }}classAddextendsOperator<Double> {publicAdd() { super("+"); } @Overridepublicvoidprocess(finalStack<Double> stack) throwsIllegalArgumentException {if (stack.isEmpty())thrownewIllegalArgumentException("Input stack should not be empty.");finalDouble num1 =stack.pop();if (stack.isEmpty())thrownewIllegalArgumentException("Input stack should contain at least 2 numbers.");finalDouble num2 =stack.pop();stack.add(num1 + num2); }}classSubtractextendsOperator<Double> {publicSubtract() { super("-"); } @Overridepublicvoidprocess(finalStack<Double> stack) throwsIllegalArgumentException {if (stack.isEmpty())thrownewIllegalArgumentException("Input stack should not be empty.");finalDouble num1 =stack.pop();if (stack.isEmpty())thrownewIllegalArgumentException("Input stack should contain at least 2 numbers.");finalDouble num2 =stack.pop();stack.add(num1 - num2); }}classMultiplyextendsOperator<Double> {publicMultiply() { super("*"); } @Overridepublicvoidprocess(finalStack<Double> stack) throwsIllegalArgumentException {if (stack.isEmpty())thrownewIllegalArgumentException("Input stack should not be empty.");finalDouble num1 =stack.pop();if (stack.isEmpty())thrownewIllegalArgumentException("Input stack should contain at least 2 numbers.");finalDouble num2 =stack.pop();stack.add(num1 * num2); }}classDivideextendsOperator<Double> {publicDivide() { super("/"); } @Overridepublicvoidprocess(finalStack<Double> stack) throwsIllegalArgumentException {if (stack.isEmpty())thrownewIllegalArgumentException("Input stack should not be empty.");finalDouble num1 =stack.pop();if (stack.isEmpty())thrownewIllegalArgumentException("Input stack should contain at least 2 numbers.");finalDouble num2 =stack.pop();if (num2 ==0) thrownewIllegalArgumentException("Input demoninator should not equal to 0.");stack.add(num1 / num2); }}classTokenFactory {privateMap<String,Operator<Double>> operators;publicTokenFactory() {this.operators=newHashMap<String,Operator<Double>>();operators.put("+",newAdd());operators.put("-",newSubtract());operators.put("*",newMultiply());operators.put("/",newDivide()); }publicToken<Double> getToken(String token) throwsIllegalArgumentException {if (operators.containsKey(token)) {returnoperators.get(token); } else {try {Double operand =Double.parseDouble(token);returnnewOperand<Double>(operand); } catch(Exception e) {thrownewIllegalArgumentException(e.toString()); } } }}classRPNCalculator {privateTokenFactory tokenFactory;privateStack<Double> stack;publicRPNCalculator() {this.tokenFactory=newTokenFactory();this.stack=newStack<Double>(); }publicDoublecalculate(List<String> formula) throwsIllegalArgumentException {if (formula.size() ==0) return0.0;try {for (String s : formula) {tokenFactory.getToken(s).process(stack); } } catch (Exception e) {thrownewIllegalArgumentException(e.toString()); }Double result =stack.pop();if (!stack.isEmpty()) {thrownewIllegalArgumentException("Input is not valid."); }return result; }}publicclassCalculator {publicstaticvoidmain(String[] args) {List<String> test =Arrays.asList("4","5","13","/","*");RPNCalculator calculator =newRPNCalculator();Double r =calculator.calculate(test);System.out.println(r); }}
using namespace std;
class Token {
public: Token() {};
virtual ~Token() = 0;
virtual bool isOperator() const = 0;
virtual void process(stack &stk) const = 0;
};
Token::~Token() {}
class Operand : public Token {
public: Operand(const string &str) {
m_val = stod(str);
}
double val() const {
return m_val;
}
virtual bool isOperator() const {
return false;
}
virtual void process(stack &stk) const {
stk.push(m_val);
}
private: double m_val;
};
class Operator : public Token {
public: Operator(const string &type) {
m_type = type;
}
const string & type() const {
return m_type;
}
virtual ~Operator() = 0;
virtual bool isOperator() const {
return true;
}
private: string m_type;
};
Operator::~Operator() {}
class Add : public Operator {
public: Add() : Operator("+") {}
virtual void process(stack &stk) const {
if (stk.empty()) throw runtime_error("illegal operation on Div: stack underflow.");
double num2 = stk.top();
stk.pop();
if (stk.empty()) throw runtime_error("illegal operation on Div: stack underflow.");
double num1 = stk.top();
stk.pop();
stk.push(num1 + num2);
}
};
class Sub : public Operator {
public: Sub() : Operator("+") {}
virtual void process(stack &stk) const {
if (stk.empty()) throw runtime_error("illegal operation on Div: stack underflow.");
double num2 = stk.top();
stk.pop();
if (stk.empty()) throw runtime_error("illegal operation on Div: stack underflow.");
double num1 = stk.top();
stk.pop();
stk.push(num1 - num2);
}
};
class Mul : public Operator {
public: Mul() : Operator("+") {}
virtual void process(stack &stk) const {
if (stk.empty()) throw runtime_error("illegal operation on Div: stack underflow.");
double num2 = stk.top();
stk.pop();
if (stk.empty()) throw runtime_error("illegal operation on Div: stack underflow.");
double num1 = stk.top();
stk.pop();
stk.push(num1 * num2);
}
};
class Div : public Operator {
public: Div() : Operator("+") {}
virtual void process(stack &stk) const {
if (stk.empty()) throw runtime_error("illegal operation on Div: stack underflow.");
double num2 = stk.top();
stk.pop();
if (stk.empty()) throw runtime_error("illegal operation on Div: stack underflow.");
double num1 = stk.top();
stk.pop();
stk.push(num1 / num2);
}
};
class TokenFactory {
public: TokenFactory() {
operators["+"] = new Add();
operators["-"] = new Sub();
operators["*"] = new Mul();
operators["/"] = new Div();
}
Token * create(const string ¶m) {
if (operators.find(param) != operators.end())
return operators[param];
else
return new Operand(param);
}
private: unordered_map operators;
};
class RPNCalculator {
public:
double calculate(const vector &formula) {
try {
for (int i = 0; i < formula.size(); ++ i) {
m_factory.create(formula[i])->process(m_stk);
}
} catch(const exception &e) {
cout << e.what() << endl; return -1;
}
double result = m_stk.top();
m_stk.pop();
if (!m_stk.empty()) {
cout << "invalid formula. " << endl;
return -1;
}
return result;
}
private:
TokenFactory m_factory;
stack m_stk;
};
class Calculator {
int main() {
vector f = {"4", "5", "13", "/", "+"};
RPNCalculator c;
cout << c.calculate(f) << endl;
return 0;
}
}
Follow Ups
token -- operand and operator inherit from token
unary and ternary operators -- add a variable of NumOperands
factory design pattern
Factory design pattern is a class where you can hide the creation logic of all sub-classes. Typically, it would require a type and generate an object of sub-class. Essentially, itโs a mapping from types sub-classes.
struct Node {
int parentIdx;
bool valid;
bool visited;
Node(int pi) : parentIdx(pi), valid(true), visited(false) {}
};
class ArrayTree {
public:
ArrayTree(vector nums) {
for (int i : nums) {
nodes.push_back(new Node(i)); size ++;
}
}
void deleteSubtree(int idx) {
if (!nodes[idx]->valid) // if already deleted
return;
reset(); // reset valid nodes back to unvisited
nodes[idx]->valid = false;
nodes[idx]->visited = true;
size --;
for (int i = 0; i < nodes.size(); ++ i) {
if (nodes[i]->visited)
continue;
explore(i);
}
}
private:
vector nodes;
int size;
bool explore(int idx) {
// if current is root or is already visited
if (nodes[idx]->parentIdx == -1 || nodes[idx]->visited) {
nodes[idx]->visited = true;
return nodes[idx]->valid;
}
nodes[idx]->visited = true;
// current validness depends on parent validness
bool isParentValid = explore(nodes[idx]->parentIdx);
if (nodes[idx]->valid != isParentValid) {
nodes[idx]->valid = isParentValid;
size --; // only decrement size when change from valid to invalid
}
return isParentValid;
}
void reset() {
for (Node * n : nodes) {
if (n->valid)
n->visited = false;
}
}
};
int main() {
vector<int> nums = {1, 5, 5, 2, 2, -1, 3};
ArrayTree at(nums);
at.print();
at.deleteSubtree(3);
at.print();
at.deleteSubtree(6);
at.print();
at.deleteSubtree(2);
at.print();
return 0;
}
Follow Ups
Update tree size
Corner cases
Index is out of range
delete subtree which already removed
Node cannot be changed.
use a boolean array to store the visited indexes.
Round 2 Blocking Queues & Slow Web Diagnose
Question 1: Blocking Queues
Suppose you have two independent blocking queues that will keep getting new data, the new data will always be greater than the last element of the queue it is going to. You can only use getNext() to get the data from these two blocking queues and each data can be fetched only once. Write a program to output all pairs of data from these two blocking queues that have difference smaller than 1.
Because the data comes from two blocking queues, the implementation of
non-streaming version would be two queues and call calculatePairs on different
queue order.
However, becasue the blocking queue could be blocked, because there is no new
incoming data. Thus two threads would be the solution.
C++ code is coyied from somewhere else
Java code is based on the C++ code, and it works.
// this is the final result containing timestamp pairs < 1 vector > result;
// queue defined to stored numbers from streams list Q1;
// use list so we can iterate list Q2;
// the lock shared between threads Lock mutex;
// this is a utility function
void calculate(list &q1, list &q2, double val) {
q1.push(val);
if (!q2.empty()) {
while (!q2.empty() && val - q2.front() >= 1) q2.pop();
for (double num : q2) {
if (abs(val - num) < 1)
result.push_back(make_pair(val, num));
else break;
}
}
}
// function that will be executed by thread 1
void task1(Stream s) {
while (true) {
double val = s.getNext();
mutex.lock();
calculate(Q1, Q2, val);
mutex.unlock();
}
}
// function that will be executed by thread 2 void
task2(Stream s) {
while (true) {
double val = s.getNext();
mutex.lock();
calculate(Q2, Q1, val);
mutex.unlock();
}
}
int main() {
// incoming streams
Stream S1 = {0.2, 1.4, 3.0};
Stream S2 = {2.0, 2.1, 4.5};
// create the threads
thread t1(task1, S1);
thread t2(task2, S2);
// start the threads
t1.join();
t2.join();
}
It should use a list to store the data from each blocking queue.
Lock is the same, it should lock before the calculation and release the lock afterwards.
The thread input should be like (List<List<Double>> queues, int qIndex)
Each thread need to maintain a list of indexes which point to the un-explored position of other queues.
Every time a thread get a new data, start from the current index and find the last index suite the condition of each other queues.
Question 2: Slow Web Accessing
When does it happen? How frequently ?
How slower compare to the normal?
Where does it happen? All places or only several places?
Is there a monitor on the full stack?
Host & service health check
Overall host performance (CPU, Mem, I/O, Disk and etc)
Time of request
Time of back end request
Database response time
Check bandwidth, there are several website to test the bandwidth
Check client device performance (CPU, Mem)
Check DNS, try different ip of the host, Ping the host
Java script issue
Render-blocking, React, life-circle state update
CDN? (content delivery network)
Check the request/response time from Browser Develop Tool. chrome -> develop tools -> network
By checking the develop tool, we could know which request took longest / longer time than normal. So it could give us some evidence / guide to the next step.
Before diving into the backend diagnoses. I have something to say in front. Backend services should have a series of metrics so that the engineer could targeting the problem more easily.
Load Balance
If there was any monitor of the hosts
CPU, Mem, I/O, load
Compare with the historical record, it maybe could give some clue.
Try different request, check whether all request are slow or only some certain ones
Access to the host, check the logs, if there were something like "TraceId" of each request, it would help a lot on find the logs, could just grep it.
It maybe direct the request to one server. If so, it maybe initial design wasn't optimised or need to change the balance strategy.
Backend Services
Monitor is essential.
Overall cluster / hosts performance, CPU, Mem, I/O, Load and etc.
Also disk sometime would cause the problem
Check the service health, if some of the services are down, it could be the reason.
Check request from log by some tracer id
There maybe a loop between services for some certain requests
Tracer Id shows the path of the a request, so it is very useful to diagnosis the problem
Check exceptions from the log, it may cause the problem
Use some command like top on a host.
Enable debug level of the logging, more information, the better.
Message Queue
Not all backend has message queue
Check the lag of topics, maybe there are too many waiting requests on a topic.
Check cluster, like for Kafka, check heath of leader and etc. If leader is down, it maybe struggle on election.
consumer group, like some servers are down.
As backend services, database / cluster should also has the metrics to help the diagnose and monitor the performance
Overall I/O, space, performance
Too many connections
Database is slow
Should design another cache layer between services and database.
Data percentage
Some of the data base performance linked with the consumed space.
Like Cassandra, when it's doing the compaction, it may slow the performance.
Apply retention policy
Some of the nodes in database cluster were down, which raise the internal communications.
Maybe another database cluster and apply sharding.
The solution should start from DP solution. The testing cases should be added at beginning.
Step 1: Recursive Solution
Step 2: DP solution
Step 3: Backtracking
Dp solution and backtrack solution are copied from leetcode
classSolution {publicbooleanisMatch(String s,String p) {int sLen =s.length(), pLen =p.length();// base casesif (p.equals(s) ||p.equals("*")) returntrue;if (p.isEmpty() ||s.isEmpty()) returnfalse;// init all matrix except [0][0] element as Falseboolean[][] d =newboolean[pLen +1][sLen +1]; d[0][0] =true;// DP computefor(int pIdx =1; pIdx < pLen +1; pIdx++) {// the current character in the pattern is '*'if (p.charAt(pIdx -1) =='*') {int sIdx =1;// d[p_idx - 1][s_idx - 1] is a string-pattern match// on the previous step, i.e. one character before.// Find the first idx in string with the previous math.while ((!d[pIdx -1][sIdx -1]) && (sIdx < sLen +1)) sIdx++;// If (string) matches (pattern),// when (string) matches (pattern)* as well d[pIdx][sIdx -1] = d[pIdx -1][sIdx -1];// If (string) matches (pattern),// when (string)(whatever_characters) matches (pattern)* as wellwhile (sIdx < sLen +1) d[pIdx][sIdx++] =true; }// the current character in the pattern is '?'elseif (p.charAt(pIdx -1) =='?') {for(int sIdx =1; sIdx < sLen +1; sIdx++) d[pIdx][sIdx] = d[pIdx -1][sIdx -1]; }// the current character in the pattern is not '*' or '?'else {for(int sIdx =1; sIdx < sLen +1; sIdx++) {// Match is possible if there is a previous match// and current characters are the same d[pIdx][sIdx] = d[pIdx -1][sIdx -1] && (p.charAt(pIdx -1) ==s.charAt(sIdx -1)); } } }return d[pLen][sLen]; }}
classSolution {publicbooleanisMatch(String s,String p) {int sLen =s.length(), pLen =p.length();int sIdx =0, pIdx =0;int starIdx =-1, sTmpIdx =-1;while (sIdx < sLen) {// If the pattern caracter = string character// or pattern character = '?'if (pIdx < pLen && (p.charAt(pIdx) =='?'||p.charAt(pIdx) ==s.charAt(sIdx))){++sIdx;++pIdx; }// If pattern character = '*'elseif (pIdx < pLen &&p.charAt(pIdx) =='*') {// Check the situation// when '*' matches no characters starIdx = pIdx; sTmpIdx = sIdx;++pIdx; }// If pattern character != string character// or pattern is used up// and there was no '*' character in pattern elseif (starIdx ==-1) {returnfalse; }// If pattern character != string character// or pattern is used up// and there was '*' character in pattern beforeelse {// Backtrack: check the situation// when '*' matches one more character pIdx = starIdx +1; sIdx = sTmpIdx +1; sTmpIdx = sIdx; } }// The remaining characters in the pattern should all be '*' charactersfor(int i = pIdx; i < pLen; i++)if (p.charAt(i) !='*') returnfalse;returntrue; }}
The for loop should be trivial.
Bit mask is what interveiwer wanted. It should be explained clearly.
publicbooleanisPowerOfFour(int n) {if (n<=0) returnfalse;while (n %4==0) n/=4;return n ==1;}
// if it will be called lots of times. the good idea would be store the precomputed// results in a map.classPowers {privateint n =15;publicList<Integer> nums =newArrayList();Powers() {int lastNum =1;nums.add(lastNum);for (int i =1; i < n +1; ++i) { lastNum = lastNum *4;nums.add(lastNum); } }}classSolution {publicstaticPowers p =newPowers();publicbooleanisPowerOfFour(int num) {returnp.nums.contains(num); }}
// explain:// 1: the number should also be power of two. // If a number is power of 2, there only one 1 digit in binary number.// So num - 1 will eliminate the last 1, so (num & (num - 1)) == 0// 2: power of 4 means the digit 1 should on the even position (start from 0). // In this way, the bit mask will be like 10101010 -> 1010|2 = 10|10 = a|16public boolean isPowerOfFour(int num) {return num >0&& ((num & (num-1)) ==0) && ((num &0xaaaaaaaa) ==0);}
Question 2: Random Iterator Dividable by 5
Using a random number iterator to crate an iterator that only return multiply of 5
implement next(), hasNext(), remove()
Solution (the question is bit of blur so the solution is based on my understanding)
The class should implement Iterator<Integer>
add nextValue and hasNextValue to the class.
remove the element from the container.
Output numbers only could mod by 5.
Remove some elements from the container
Check again to make sure the elements are removed.
dead cell is born if it has 2 or 3 Y-neighbours alive
living cell survives if it has 2 or 4 Y-neighbours
2D solution
follow up
infinite grid
large grid sparse
distributed system design
* 1D and 2D solution is trivial.
o in place solution would be prefered
o need to ask about the boarder
* Follow ups:
o Infinite grid
o Large grid but alive points are sparse
o Solve it using distribued system
classSolution {publicvoidgameOfLife(int[][] board) {// state:// curr\next | alive | dead// alive | 1 | -1// dead | 2 | 0int row =board.length;if (row ==0) return;int col = board[0].length;if (col ==0) return;for (int i=0;i<row;i++) {for (int j=0;j<col;j++) {int count =0;for (int k =-1; k<=1;k++) {for (int n=-1;n<=1;n++) {if (n ==0&& k ==0) continue;if (i+k >=0&& i+k<row && j+n >=0&& j+n<col) count +=Math.abs(board[i+k][j+n]) ==1?1:0; } }// Rule 1 or Rule 3if ((board[i][j] ==1) && (count <2|| count >3)) {// -1 signifies the cell is now dead but originally was live. board[i][j] =-1; }// Rule 4if (board[i][j] ==0&& count ==3) {// 2 signifies the cell is now live but was originally dead. board[i][j] =2; } } }// Get the final representation for the newly updated board.for (int i =0; i < row; i++) {for (int j =0; j < col; j++) {if (board[i][j] >0) { board[i][j] =1; } else { board[i][j] =0; } } } }}
* Infinite Grid
o Data stracture: Map<Integer, Map<Integer, Integer>> lives
o Better to define a new class to handle the get, put, update and etc
o Infinite Java is the Java version of infinite board
* Sparse Points in very large grid
o It should be the same as above.
* Multi thread / multi process / GPU / distributed system
o Slice the board int to multiple blocks of rowls
o Assign these block / sub maps to each server/thread
. if we use thread, read is safe
o A zookeeper should record the state of each server
o If all servers' state are the same, then start next step
o In order to calculate the elements on boarder, a store layer or server
communicate with each other (ask zookeeper first).
Highlight can be implemented by add another flag in tree node
Two stacks for Redo and Undo
Implement a class of Actions
Stack of Actions
Save & Load
Serialise & Deserialise tree
Search
Boyer-Moore Search
Rope data structure require two operations
1: concat
simplist solution is to create a new node: node.left = root, node.right = inputNode
Need to balance the tree after each concat
2: split
Update root to the left side and return the right side node.
Then the following operations
* Insert(index, str)
o inputNode = new Node(str);
o lastNode = split(index);
o concat(inputNode);
o concat(lastNode);
* Delete(start, end)
o lastNode = split(end)
o deleteNode = split(start)
o concat(lastNode)
* Index(index)
o binary search
* Highlight(start, end)
o lastNode = split(end)
o highlightNode = split(start)
o highlight(highlightNode)
o concat(highlightNode)
o concat(lastNode)
* Search
o Iteriter inorder traverse.
o Boyer-Moore search algorithm.
Solution key points
* DummyHead and DummyTail points to the head and tail of the double linked list
* Apply removeNode and addNode.
o removeNode:
. remove the node from the list, connect its left and right,
o addNode:
. Add the node to the head of the double linked list
* put(key, value)
o check the existence of the key, update the value, update the node.
o check size limit
protected boolean removeEldestEntry(Map.Entry eldest) {
return size() > CAPACITY;
}
// Collections wrapper, Most straight farward solution. Less code changeMap<T,T> m =Collections.synchronizedMap(newLinkedHashMap<T,T>(capacity));
Solution key points
* DummyHead and DummyTail points to the head and tail of the double linked list
* Apply removeNode and addNode.
o removeNode:
. remove the node from the list, connect its left and right,
o addNode:
. Add the node to the head of the double linked list
* put(key, value)
o check the existence of the key, update the value, update the node.
o check size limit
Data structure: three maps to keep k-v, k-count, count-list<key> and minCount
* Key-Value map
o Stores the all the key-value
o HashMap<T, T>
* Key-Count map
o Store the count of the key
o HashMap<T, Integer>
* Count-List<Key> map
o Store the list of keys of each count
o HashMap<Integer, LinkedHashSet<T>>
* minCount
o keep track the min count
Testing case should cover:
* ไธคไธชๆฐ็ป้ฝไธบ็ฉบ
* ๆๅ ถไธญไธไธชๆฐ็ปไธบ็ฉบ๏ผๅฆๅคไธไธชๆฐ็ป้ฟๅบฆไธบๅฅๆฐ/ๅถๆฐ
* ๆฐ็ป้ฟๅบฆ้ฝๆฏๅฅๆฐ
* ๆฐ็ป้ฟๅบฆ้ฝๆฏๅถๆฐ
* ๆฐ็ป้ฟๅบฆไธๅฅไธๅถ
* index over the constraint
* overlap & non overlap
Because it is a semi open-end question, there is no real correct answer. The following solution is based on my own understanding and above link.
It should use
State Pattern
Mediator Pattern
// Need to implement the following classesclassAccountStoreclassCardHandlerclassCashDispenserclassCashIntake// Then there is a menu function in ATM class. Such asswitch (choice) {case LOGIN://TODO: implement function to support user login}// ATM class has the following membersAccountStore _accountstore; // store the account created at this ATMCardHandler _cardhanlder; // handles card read returnCashDispenser _cashdispenser; // handles cash withdrawCashIntake _cashintake; // handles cash deposit
There are several questions should be asked in front
* output ๆไปไน้ๅถๅ?
Assumption: ๅช่ฝๆฏ20็พๅ ็ๅๆฐ
* Output ไผไธ่ถณๅ?
Assumption: ATMๆฐธ่ฟๆ่ถณๅค็ไฝ้ข (Bonus: ่ฟ้ๅฏไปฅ่่ๅฆๆไธๅค็่ฏๅบ่ฏฅๆไนๅค็)
* Multi Accounts bounded on one card?
* Turn on or off?
* Can we assume there will be no transactions when using ATM
o like if want to withdraw money but at mean time direct debt cut some money
o This is concurrent
* Should message between ATM and Bank encrypt?
// Here I only present the state translate codepublicvoidstartServe() {try {switch(state) {case CREATEACCOUNT:break;case NOTACTIVE:char[] accountNum =displayConsole.inputAccountNumber();if (accountNumberValidation(accountNum)) { account =cardHandler.getAccount(newString(accountNum)); session =createNewSession();setState(AtmState.SERVEACCOUNT); }break;case SERVEACCOUNT:checkSesssion();// card inserted but not loggedinif (account !=null&&!account.isAuthed()) login();// card insert and account authedelseif (account !=null&&account.isAuthed()) menu();// no card, waiting for next serveelsesetState(AtmState.NOTACTIVE);break;case ERROR:break;default:break; } } catch (Exception e) {log.warning(e.toString()); state =AtmState.ERROR; } }privatevoidlogin() throws Exception {for (int i=0;i<5;i++) {if (account.getAuth(displayConsole.inputPassword())) {return; } else {displayConsole.outputWrongPassword(); } }cardHandler.retainCard();// print somethingsetState(AtmState.NOTACTIVE); }privatevoidmenu() throws Exception {AccountType fromType;AccountType toType;float amount;try {switch (displayConsole.inputActionSelection()) {case QUERY:checkSesssion(); fromType =displayConsole.chooseFromAccount();account.query(fromType);break;case TRANSFER:do {checkSesssion(); fromType =displayConsole.chooseFromAccount(); toType =displayConsole.chooseToAccount(); amount =displayConsole.inputAmount();account.transfer(fromType, toType, amount); } while (displayConsole.inputNextStep());break;case WITHDRAWL:do {checkSesssion(); fromType =displayConsole.chooseFromAccount(); amount =displayConsole.inputAmount();account.withdraw(fromType, amount);cashExpenserHandler.popCash(amount); } while (displayConsole.inputNextStep());break;case DEPOSIT:do {checkSesssion(); toType =displayConsole.chooseToAccount(); amount =displayConsole.inputAmount();cashEnvelopHandler.countCash(amount);account.deposit(toType, amount); } while (displayConsole.inputNextStep());break;case LOGOUT:cardHandler.returnCard();displayConsole.outputEndMessage();setState(AtmState.NOTACTIVE);default:checkSesssion();break; } } catch (Exception e) {if (e.getMessage().startsWith("Insufficient Amount")) {displayConsole.outputInsufficientAmount(); } } }privatevoidsetState(AtmState state) {this.state= state;startServe(); }
Set 4
The questions in this set are varies. I add all questions whose frequency is higher than the others in this set. Also some of the questions from other set would also be asked in this set.
We need to add locks on each element. It isn't clear what's the data structure. Here is my assumptions
An array to store the count of each element
An map to store the count of each element
Locks :
ReentrantLock
Semaphore: Signal, like limit the number of the thread
Mutex:
Possible solutions
* It is a producer - consumer model
* Lock
o Some mates said about mutex, semaphore, sychronization and ReeentrantLock
* The code is based on my search and understanding. I left the eggLock to demo
that when there is no lock, it may be error message.
Because currently they are all virtual interviews. This problem may not be asked.
It should use pull and push model.
Pull model for the personal websites, like fackbook or twitter
Push model for the general websites, like wsj or nytimes
* Feed system
* Web crawler
* Search
Average: maintain a total sum, average = sum / stack size
Min: use a stack to store min
Max: use a stack to store max
mode: Like LFU cache, but keep the max instead of min.
Median: Two queues and a map to track the removed ones
Here I only implements the average, min, max and mode.
Because mode is quite complex so I create another class to handle it.
It would be better to design the unit test.
classMode {privateMap<Integer,Integer> valueCount;privateMap<Integer,LinkedHashSet<Integer>> countList;privateint max;publicMode() { valueCount =newHashMap<>(); countList =newHashMap<>(); max =0; }publicvoidput(int val) {if (valueCount.containsKey(val)) {int count =valueCount.get(val);valueCount.put(val, count +1);countList.get(count).remove(val);if (countList.get(count).isEmpty()) countList.remove(count);countList.computeIfAbsent(count +1, x ->newLinkedHashSet<>()).add(val);if (max == count) max++; } else {valueCount.put(val,1);if (max ==0) max++;countList.computeIfAbsent(1, x ->newLinkedHashSet<>()).add(val); } }publicvoidremove(int val) {if (valueCount.containsKey(val)) {int count =valueCount.get(val);if (count-1==0) {valueCount.remove(val); } else {valueCount.put(val, count-1); }countList.get(count).remove(val);if (count == max &&countList.get(count).isEmpty()) max--;if (countList.get(count).isEmpty()) countList.remove(count);countList.computeIfAbsent(count -1, x ->newLinkedHashSet<>()).add(val); } } /** * @return oldest most frequent element in the stack * @throwsException */publicintgetMostFrequentValue() throwsException {if (valueCount.isEmpty()) thrownewNoSuchElementException("Stack is empty.");returncountList.get(max).iterator().next(); }}
Weighted samplingใ็ปไธไธชarray of tuple็๏ผweight, data๏ผ๏ผ่ฆๆฑไปฅ็ปๅฎ็ๆฆ็sampleๆฐๆฎใ ๆไผ็ญๆกๆฏbinary indexd tree log(n)็่ฏปๅcomplexity๏ผ่ไธๆฏๆinsert/delete๏ผ้ฝๆฏlog(n) ๆ็ปๅบๆฎ้็ญๆก๏ผ่ฎฐไฝๅทฒๆ็weight็ถๅๆฅๆพใ้ข่ฏๅฎไน่ฎคๅฏไบใ
* Game
o Game class should have a board and some player
o it should control when start and end
* Board
o Board should record the players location.
o interfaces:
. registerPlayer(Player)
. int isCloser(Player, Move)
* Player
o Player should only record the result from prev move, for decision
o interfaces:
. int[] nextMove();
. setResult(int)
ๆๅคงๆฆๆ่ไบไธไธไนฑ่ฏดไบไธไธชheadโฆโฆๅๆฅwork out math็ๆถๅๆๅ็ฐheadๅtail็ๆถ้ดๆฏ็ธๅ็๏ผๆๅฐฑๅผๅง่งๅพๅบ่ฏฅๆฏmidwayๅ็็ๆถ้ดๆ้ฟ๏ผ(่ฟไธชๆถๅๆไธไธชๅ่ฎพๆฏๅ้ๅๅ ้็ๅ ้ๅบฆๆฏ็ธๅ็)ใ
้ข่ฏๅฎ่ฏดๅฏน๏ผ็ถๅๅฐฑ้ฎhow much longer? ็ถๅ็ปไบไธไธชๆ็คบ็จs = 1/2 a t t่ฟไธชๅ ฌๅผๅปๆจ๏ผๆๅคงๆฆๅไบๅ ่ก่ทไป่ฏดๅคงๆฆๆฏ(sqrt{2} - 1) longer๏ผไปๆ็นๆ่ฎถๅ ไธบไปๅฅฝๅ่งๅพๆๅพๅคๆญฅ้ชค่ทณๆไบโฆโฆanywayไป่งๅพๆฒก้ฎ้ข๏ผๅๆฅๅ้ฎๅฆๆๅ้ๅๅ ้็ๅ ้ๅบฆไธๅ้ฃๆไนๅ๏ผๅชไธช็นๅ็็ๆถ้ดๆ้ฟ๏ผๆ็ดๆฅ็ปไบไธคไธ็ไบไธไธช่กจ่พพๅผๅคงๆฆๅฐฑ่ฏดๆฏ่ฆๅจ่ฝฆ็(a2 / (a1 + a2))ๅ็็ๅฐๆนโฆโฆ้ข่ฏๅฎๅฐฑ้ฎไธบๅฅ๏ผๆๅฐ่ฏwork out mathไบๅๅคฉๆชๆ๏ผๅๆญฃๅคงๆฆๅฐฑๆฏ1/2 a1 t1 t1 = x, 1/2 a2 t2 *t2 = S - x็ถๅๅปmaximize t1 + t2็ๅผ๏ผๅพๆๆพ็ๆ็ๆฐๅญฆๆฐดๅนณๅทฒ็ถไธ่ถณไปฅ่งฃๅณ่ฟไธช้ฎ้ขไบโฆโฆ