回复: 85
跳转到指定楼层
上一主题 下一主题
收起左侧

我打算给你们一份最全的Two Sigma面经总结

   
全局:

2016(10-12月) 码农类General 硕士 全职@twosigma - 内推 - 技术电面 Onsite  | | Fail | 应届毕业生
很多人反映不方便看还有求发邮箱,在这里一并回复了,附件里给个html的版本(没办法Evernote只能导出成这个。。)。

=================

实在是在床上从1点翻滚到了5点没睡着,就上来发了这篇。

我拿到的面试并不多,TS是第一家onsite的,当时也是压了好大一把,可惜还是水平不够。

我跪在了下午。虽然当时觉得发挥除了自己的最好水平,跪了我也没什么好说,觉得这就是我了。可是后来想想觉得还是有上升得空间T T人世间最悲伤的事莫过于此……

觉得是自己的project没讲好。一方面他们想要找有相关经验的人不假,另一方面我自己又没有发挥好导致我做得看起来好像很水……所以,再见了。

时间线:
- 九月多朋友向联系他的recruiter推荐了我
- 十月初hr聊
- 两至三周后OA
- 又两周后电面
- 十二月初onsite

P.S 我没有权限贴链接………………
P.S.S 少了副图,有需要我再贴吧
P.S.S.S OA也有诀窍,不要跪得不明不白,也是有需要我再讲吧
P.S.S.S.S (...) 最后求点大米吧,实在是干什么都好不方便啊…………


Behavioral

Bigger impact, newer/better technology, more responsbilities, work with smart people.
Software Engineering is an industry of continous learning, and so should I, also I noticed that you have a learning culture here, a place of learning.
Rather than many financial companies that keep technology as a back office, I'm looking for something that is tech-driven. I always
believe that technology is the key on the road to successful strategy.
life is about making decisions, it is like investments.
We're downtown, but we're not Wall Street.


- How it works:
look for meaningful patterns in the world’s data. Then we use these insights to create investment strategies.
Pattern. Meaning. Relationships.
Power of data and technology.
Predict the movement of the market (retirement investment).


- Why Two Sigma?
As a new grad, I’m looking for a place to grow and expand myself.

每轮都有自我介绍的时间和面试官介绍自己的时间

围绕围绕,扯回去扯回去!


Questions to ask
  • Could you briefly introduce Two Sigma? What do you guys do? And what does your team do?
  • What’s your typical day? I mean, as an engineer, how usually do you spend your day?
  • Halite the AI challenge, last time the 2016 TS cup, why do you guys so focus on AI and Robot?
  • Things that engineers build, are them only being used internally? And Also are you using any products of software from other companies?
  • About the trading and all related operations, are they human involved?  In other words, how much do you guys trust decisions made by machines?



Phone
What's your most challenging project?

Hash Table

What is a hash table? When to use? Why use it?


Given a (key, value) pair, hash table is data structure which converts the key to an index and then store the value somewhere using that index.

Generally, we can think of it a as a mapping from key to value.


Hash function generates index of buckets or slots using key.

Ideally, it maps key to a unique bucket.  The best situation is it provides a uniform distribution of hash values.


Operations cost:
- Constant, amortized O(1)
- worst case O(n) for search & deletion (add flag to fix it)

Size:
- power of 2
- prime number, good for even poorly designed hash function

Resizing (resize + insert again O(n) in average (n/2)
- Load factor = (# of entries) / (# of buckets)
- keep size within a good range (not too many collision, not too large wasted memory)


Open Addressing (close hashing) is method of collision resolution in hash tables. It’s resolved by probing. Probing includes linear probing, quadratic probing and double hashing.

Linear probing:
Search: Find next available slot.
Insert:
Delete (Trouble):
- Iterate through the following slots until find an empty slot or move one back to this slot (recursively)
- Or use flag

Problems happen when there’s primary clustering. It means two records are mapped to the same index which causes one of them to move. And afterwards collisions increases during inserting more key value pair into hash table. A tendency that a collision will cause more nearby collisions.

With poorly designed hash function, i.e., hash function that would not make inputs uniformly distributed, linear probing could be slower than quadratic probing and double hashing.


Someone implement hash table and it is slow, why?
- poor hash function
- bad open addressing strategy



Use hash table to store data, but there is much more data than the machine's RAM, how to deal with that?
    add one more machine, rehash and reconstruct the hash table




Process vs Threads


In computing, a process is an instance of a computer program that is being executed. It contains the program code and its current activity. Depending on the operating system (OS), a process may be made up of multiple threads of execution that execute instructions concurrently.

In computer science, a thread of execution is the smallest sequence of programmed instructions that can be managed independently by a scheduler, which is typically a part of the operating system.


Each process provides the resources needed to execute a program. A process has a virtual address space, executable code, open handles to system objects, a security context, a unique process identifier, environment variables, a priority class, minimum and maximum working set sizes, and at least one thread of execution. Each process is started with a single thread, often called the primary thread, but can create additional threads from any of its threads.
A thread is the entity within a process that can be scheduled for execution. All threads of a process share its virtual address space and system resources. In addition, each thread maintains exception handlers, a scheduling priority, thread local storage, a unique thread identifier, and a set of structures the system will use to save the thread context until it is scheduled.


Typical difference is, processes run in separated memory while threads run in shared memory.
  • processes are typically independent, while threads exist as subsets of a process
  • processes carry considerably more state information than threads, whereas multiple threads within a process share process state as well as memory and other resources
  • processes have separate address spaces, whereas threads share their address space
  • processes interact only through system-provided inter-process communication mechanisms
  • context switching between threads in the same process is typically faster than context switching between processes.


How to communicate? IPC vs ITC (Inter-Process Communication vs Inter-Thread Communications)
IPC:
- File
A record stored on disk, or a record synthesized on demand by a file server, which can be accessed by multiple processes.


- Socket
A data stream sent over a network interface, either to a different process on the same computer or to another computer on the network. Typically byte-oriented, sockets rarely preserve message boundaries. Data written through a socket requires formatting to preserve message boundaries.


- Message Queue
A data stream similar to a socket, but which usually preserves message boundaries. Typically implemented by the operating system, they allow multiple processes to read and write to the message queue without being directly connected to each other.

Publish/Subscribe, Observer

- Pipe     
A unidirectional data channel. Data written to the write end of the pipe is buffered by the operating system until it is read from the read end of the pipe. Two-way data streams between processes can be achieved by creating two pipes utilizing standard input and output.

Like when we are using arrow symbol in command line.

- Shared memory     
Multiple processes are given access to the same block of memory which creates a shared buffer for the processes to communicate with each other.


- Semaphore     
A simple structure that synchronizes multiple processes acting on shared resources.


ITC:
- Synchronization primitives, like locks and semaphores
- Through Events: wait, notify

- Shared memory, cause typically they all live in the same process

Each thread has a private stack, which it can quickly add and remove items from. This makes stack based memory fast, but if you use too much stack memory, as occurs in infinite recursion, you will get a stack overflow.

All threads share a common heap. Since all threads share the same heap, access to the allocator/deallocator must be synchronized. There are various methods and libraries for avoiding allocator contention.

Some languages allow you to create private pools of memory, or individual heaps, which you can assign to a single thread.


every thread would be allocated its own memory space in stack while typically there is only one heap within one process. This means heap space is shared among all threads. Since it is global, it is faster in speed. But also, this causes synchronization issues, which could possibly slow the whole system down.

Some languages or OS my support allocating heaps for each thread.


Latency vs Throughput


Latency is the amount of time to finish an operation. Latency is the delay from input into a system to desired outcome.
Unit would be second granule.


Throughput is the amount of work we finished in a unit time.

Throughput is a measure of how many units of information a system can process in a given amount of time.



Bandwidth commonly measured in bits/second is the maximum rate that information can be transferred

Throughput is the actual rate that information is transferred
Latency the delay between the sender and the receiver decoding it, this is mainly a function of the signals travel time, and processing time at any nodes the information traverses


Throughput impacted by latency?

throughput = bandwith / rtt
rtt = latency * 2

latency up, throughput down
latency down, throughput up



Quicksort vs Merge sort

Quick sort
- in place
- average O(nlgn), worst O(n^2)

Merge sort
- average and worst O(nlgn)
- extra space O(n)

External sorting is a term for a class of sorting algorithms that can handle massive amounts of data. External sorting is required when the data being sorted do not fit into the main memory of a computing device (usually RAM) and instead they must reside in the slower external memory (usually a hard drive). External sorting typically uses a hybrid sort-merge strategy. In the sorting phase, chunks of data small enough to fit in main memory are read, sorted, and written out to a temporary file. In the merge phase, the sorted subfiles are combined into a single larger file.


The core idea, is that in the sorting phrase, the chunk of data that we need to sort could be loaded to RAM and thus apply sorting to them. Then we can write them back to the temporary file.


Both merge sort and quick sort could be used for external sorting.



Median of streaming data

Given a stream of numbers, how to calculate average, standard deviation, median?
Median: Max heap + min heap
Average: Keep track of sum & size
Standard deviation: Not other way, O(n) best?

Followup:
- what about largest (smallest) K% elements?

e.g., (n/10)th element







Design Pattern

A design pattern is a general reusable solution to a commonly occurring problem.


Each template is useful for solve a particular set of problems with some feature.

MVC Design Pattern

MVC is a design pattern for implementing user interface. It consists of three parts, Model, View and Controller, where each one of them is called components and has their own functionality.

Model manages all the data and logic of a software. It is the core component.
View is an interface responsible for taking all information from model and representing them to user.
Controller takes all commands from users sends them to model.

In this way, a software is loosely coupled and well organized into modules. We can very easily add new functions and features to it. And it is also very easy to maintain.

What other design patterns have you used?

(Creational)
Singleton -> Object Pool
Singleton is a design pattern where you allow only one instance of a class. In some cases, like its private variables don’t change, singleton is useful.

Later, to extend this we could use object pool where we allow multiple instances of a class. This could be useful when we need a couple of object at the same time while it’s expensive to create them. A good example would be service connections. We can use two hash tables to implement this. One for available objects and one for unavailable objects.

Factory -> Abstract Factory
Factory is a design pattern that allows us to dynamically specify an object’s class without calling constructor.

Prototype, Builder

(Structural)

Adapter, Facade
Adapter is a wrapper of old interface. We add it because the current function needs a new interface which is incompatible with the old one.

Facade is just a wrapper that aggregates some functionalities required by clients. By doing this, the whole system is easier to understand, to use and to test.

Composite
Composite is a design pattern that allows tree structure. It contains either variables we need, or a list objects of itself.

Proxy

(Behavioral)

Iterator
It’s just a pattern for iterating a data structure. By doing this, we can encapsulate the implementation of our own data structure and just provide the iterator interface.

State, Strategy

They both keep data as their member variables which can be changed in runtime.





Onsite
First set
First round:
Reverse Polish Notation

Make sure to know what the requirement is.

Operator (base class)
- operate(int val1, int val2)

Add,Subtract, Multiply, Divide四个class继承这个Operator base class的写法

- pay attention to Divide

Don’t over-design!

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.
- 怎么才能直接给用户binary, 让他们可以自由的添加新的operator,更好的办法是做XML / JSON的serialization


Take a look at how to use Abstract class.

design题:
一个Calculator类,包含一个stack和一个vector<Token>。

一个 Token 类,包含一个process(stack)方法。
Operand 和 Operator 继承自Token。Operand的process是向stack中push这个数字。Operator包含一个numOfOperand,process方法是从stack中pop出numOfOperand个数字后进行某种操作,结果再push进stack。

Remove subtree from tree


给的程序是用C写的,很长,大部分不用看,只需要写一个子函数,要现场编译现场跑给定一个数组,数组的每个元素就是一个节点(struct node),大概的长得像下面这样

struct node{
    int parent;
    int val;
    bool valid;
};

parent代表当前node的parent 在数组里的index,root node的parent是-1. 所以node 是child指向parent的。给定一个数组和数组的某个index,删除这个index以及它的子树(只需要将node里的valid置为false即可),只能用O(n)的空间复杂度

解法:在strcut node里面添加一个新的元素visited(一定要记得在程序里初始化node的地方,把visited设为false),代表该node是否被访问过。然后从头到尾访问输入数组。对于当前访问的元素,如果已经被visited了,则忽略。否则,沿着parent指针走,直到到达根节点(则从当前node到根节点的所有node都不需要delete),或者到达一个被标记为删除的节点(则当前node到根节点所有的node都需要被删除)

struct node
{
    int parent;
    int val;
    bool valid;
    bool visited;
};

要实现的函数大概长这样:

void DeleteSubTree(node* head, int index, int n){
    // n代表数组里面一共有n个元素
    (head+index)->visited = true;   // Set up
    (head+index)->valid = false;    // this first!!

    for(int i=0; i < n; i++){
        if ((head+i)->visited) continue; // Memorization

        if(NeedDelete(head, i)){
            label(head, i);
        }
    }
}

bool NeedDelete(node* head, int index){
    while(index != -1 && !(head+index)->visited ){
        (head+index)->visited = true;
        index = (head+index)->parent;
    }

    if(index == -1) return false;  // If finds root, return False
    return !(head+index)->valid;
}

void label(node* head, int index){
    while((head+index)->valid){  // Assumption!
        (head+index)->valid = false;
        index = (head+index)->parent;
    }
}



Follow ups:
- update tree size (capacity)
- corner case:
  • index不合法
  • 删除一个已经被删除的subtree的时候size会继续往下减


delete sub tree
改写代码题:不能在node里加入需要动态分配内存的数据结构。用左儿子右兄弟解决。

struct node {
        value: int
        isValid: bool
        leftChild, rightSibling: node*
        upParent: node*
}

linkNodes(child, parent) {
        child.upParent = parent
        child.rightSibling = parent.leftChild
        parent.leftChild = child
}

removeNode(node) {
        node.isValid = false
        node = node.leftChild
        while (node != NULL) {
                remove(node)
                node = node.rightSibling
        }

}


Second round
Two queues get elements with distance <= 1

Assuming we already get all elements on hand.

cur_ts = blocking_queue1.getNext()
q1.append(cur_ts)

while q2 and cur_ts - q2[0] > 1: # pop() for better performance in the future, explain it!!
    q2.popleft() # deque, for performance


for ts in q2:
    if abs(ts - cur_ts) <= 1:

        print ts, cur_ts

    else:

        break


Now, two blocking queues!

We use two threads, to avoid being blocked.

def retrieve_from_queue1(stream):
    ts = stream.getNext()
    calculate_pairs(q2, q1, ts)

Same thing for queue2.

Meanwhile, two threads are modifying the same data structure — q1 and q2, so we need lock.
- lock = threading.Lock()
- modify calculate_pair to “with lock:”
- finally start the threads, and run

try:
    thread.start_new_thread(thread1, (s1, ))
    thread.start_new_thread(thread2, (s2, ))
except:
    print "Couldn't start threads."
各种切入点啊,看题目要求吧!

Followups:
- 如果有多个queue,比如10个queue怎么办,lock ds (like semaphore), then do the same thing



process() {
        while (true) {
                LOCK L1
                x = s1.get()
                list1.add(x)
                UNLOCK L1

                LOCK L2
                for y in list2
                        if (abs(x - y) < 1)
                                print
                UNLOCK L2
        }

}


Slow Web Accessing


- client-server-database model
- draw diagram/model






(Start from browser)

DNS (back to front)

- cache
- test: check response time

CDN (ip address of a data center)
- cache
- test: try different ip of the host


Load balancer / Router (inside a data center)
- different kinds of request
- download, long connection, web browsing, short connection
- different protocol
- balance request numbers to different servers
- test: monitor server load and request type

Back end

- asynchronous vs synchronous response
- reduce I/O waiting time

Message queue
- distributed system

Database
- same request -> cache
- too many connections at the same time -> batch
- Database itself is slow -> in-memory database
- bad formatted, low efficient queries

- bad table design

(Back to browser)


Front end
- bad javascript
- call library, which doesn’t do well in CDN


Browser
- hardware acceleration


General / QoS
- bandwidth, low speed for transferring data
- throughput, low speed for processing data
(- error rate)



Wildcard matching

Firstly, think this through. All corner cases, test cases.


    def test_empty_string_match(self):
        self.assertTrue(is_match('', ''))
        self.assertFalse(is_match('', '?'))
        self.assertTrue(is_match('', '*'))
        self.assertFalse(is_match('', 'a*'))
        self.assertTrue(is_match('', '**'))

    def test_exact_match(self):
        self.assertTrue(is_match('a', 'a'))
        self.assertTrue(is_match('abc', 'abc'))
        self.assertFalse(is_match('abc', 'abb'))
        self.assertFalse(is_match('a', ''))

    def test_question_mark_match(self):
        self.assertTrue(is_match('a', '?'))
        self.assertFalse(is_match('ac', '?'))
        self.assertFalse(is_match('a', 'a?'))
        self.assertFalse(is_match('a', '?a'))
        self.assertFalse(is_match('a', '??'))
        self.assertTrue(is_match('ab', '??'))

    def test_star_match(self):
        self.assertTrue(is_match('', '*'))
        self.assertTrue(is_match('a', '*'))
        self.assertTrue(is_match('abc', '*'))
        self.assertTrue(is_match('abc', 'a*'))
        self.assertFalse(is_match('abc', 'b*'))
        self.assertTrue(is_match('abc', '*c'))
        self.assertFalse(is_match('abc', '*d'))
        self.assertTrue(is_match('abbbdddccc', 'a*c'))
        self.assertFalse(is_match('abc', 'a*d'))

    def test_question_mark_and_star(self):
        self.assertTrue(is_match('a', '?*'))
        self.assertTrue(is_match('a', '*?'))
        self.assertTrue(is_match('ab', '*?'))
        self.assertFalse(is_match('a', '??*'))
        self.assertTrue(is_match('abc', 'a?*c'))
        self.assertFalse(is_match('abc', 'a?*d'))
        self.assertFalse(is_match('abc', '?*?d'))
        self.assertTrue(is_match('abc', 'a***?c’))





According to this, write a naive recursion implementation. Walk them through. Make sure to illustrate the idea clearly!!!

def is_match_recursion(s, p):
    if not s: # Corner case.
        return p.count('*') == len(p)

    if not p: # Corner case.
        return not s

    if p[-1] == '?' or s[-1] == p[-1]: # Recursive call.
        return is_match(s[:-1], p[:-1])

    if p[-1] == '*’: # Recursive call.
        return is_match(s, p[:-1]) or is_match(s[:-1], p)

    return False


Two optimizations:
  • Change passing str to passing list + indices, save memory in recursive calls.
  • Avoid duplicated computation by importing memorization {(si, pi): True/False}





Extend the idea above to Dynamic Programming. Make sure to be clear about the tabular fill-up (relationship), and corner cases.

def is_match(s, p):
    m = len(s)
    n = len(p)

    matched = [[False] * (n+1) for _ in xrange(m+1)]
    matched[-1][-1] = True # Corner Case.
    for i in xrange(n): # Corner Case.
        if p != '*':
            break
        matched[-1][i] = True

    for si in xrange(m):
        for pi in xrange(n):
            if s[si] == p[pi] or p[pi] == '?’:  # Relationship.
                matched[si][pi] = matched[si-1][pi-1]
            elif p[pi] == '*’:                         # Relationship.
                matched[si][pi] = matched[si][pi-1] or matched[si-1][pi]
            else:
                matched[si][pi] = False
    return matched[m-1][n-1]





Followup, Backtracking!

si, pi = 0, 0
last_si, last_pi = None, None

while si < len(s):
    if pi < len(p) and (s[si] == p[pi] or p[pi] == '?'):
        si += 1
        pi += 1
    elif pi < len(p) and p[pi] == '*':
        last_si = si + 1
        last_pi = pi + 1
        pi += 1
    elif last_pi:
        pi = last_pi
        si = last_si
        last_si += 1
    else:
        return False



return p[pi:].count('*') == len(p) - pi

Second set
First round:
Power of 4
Of course it could be solved by brute force= =
while abs(num) > 1:
    if num % 4 != 0: return False
    num /= 4
return num == 1

It reminds me of power of 2:
num & (num-1) == 0 # power of 2
This means there’s only one bit in binary representation.

All we need to do is to add another condition.
- num > 0 and num | 0x55555555 == 0x55555555 # explain 0x55555555

- (num & 0x55555555) != 0
- (num-1) % 3 == 0 # 3n + 1


two's complement, explain negative numbers



Random iterator dividable by 5
Be clear what to remove and when to remove them!
class Iterator(object):
    def __init__(self, nums):
        self.nums = nums
        self.x = 0
        self.y = 0
        self.last_return = None

    def hasNext(self):
        while self.x < len(self.nums) and \
              self.y >= len(self.nums[self.x]):
            self.x += 1
            self.y = 0
        return self.x < len(self.nums) and self.y < len(self.nums[self.x])

    def next(self):
        if self.hasNext():
            val = self.nums[self.x][self.y]
            self.last_return = (self.x, self.y)           
            self.y += 1
            return val
        else:
            raise Exception('No more values')

    def remove(self):
        if self.last_return:
            x, y = self.last_return
            self.last_return = None
            self.nums[x].pop(y)
            self.x, self.y = x, y
        else:
            raise Exception('None couldn\'t be removed')

Mod 5 iterator.
bool hasNext() {
        # Either way is okay, hasNext() or next()
        while (self.n % 5 != 0 and Iterator::hasNext()) {
            self.n = Iterator::hasNext();
        }
        return self.n % == 0;
    }

int next() {
        if (!hasNext())
            throw runtime_error("no more elements!");

        val = self.n

        self.n = INIT_VAL # not equal to n * 5

        return val;
    }



Some theory
- 理论。给两个set,如果取他们的交集,问了各个方法的优缺点(时间复杂度+空间复杂度)
- brute force
- sort one, binary search the other one
- sort, then two pointers
- hashmap
- merge,归并排序duplicates???

- 理论。各种sorting algo 的优缺点。


- bubble, insertion
- bucket sort
- shell
- merge sort
- quick sort



Second round
Game of life
This is 1D solution.

def game_of_life_1d(arr):
    n = len(arr)

    for x in xrange(n):
        live_count = 0
        if arr[(x+1+n) % n] & 1 == 1:
            live_count += 1
        if arr[(x-1+n) % n] & 1 == 1:
            live_count += 1

        if live_count == 1:
            arr[x] *= (arr[x] + 1) % 2 * 2
        else:
            arr[x] += arr[x] * 2

    for x in xrange(n):
        arr[x] >>= 1

This is 2D solution. Ask about cross border situation.

def game_of_life_2d(grid):
    m, n = len(grid), len(grid[0])

    for x in xrange(m):
        for y in xrange(n):
            live_count = get_live_count(grid, x, y, m, n)

            #  print x, y, live_count
            if grid[x][y] == 1:
                if live_count == 2 or live_count == 3:
                    grid[x][y] += 2
            elif live_count == 3:
                grid[x][y] += 2

    for x in xrange(m):
        for y in xrange(n):
            grid[x][y] >>= 1


# Ask. Be clear about this.
def get_live_count(grid, x, y, m, n):
    live_count = 0
    if grid[x][(y+1+n) % n] & 1 == 1:
        live_count += 1
    if grid[x][(y-1+n) % n] & 1 == 1:
        live_count += 1

    if grid[(x+1+m) % m][y] & 1 == 1:
        live_count += 1
    if grid[(x-1+m) % m][y] & 1 == 1:
        live_count += 1

    if grid[(x+1+m) % m][(y+1+n) % n] & 1 == 1:
        live_count += 1
    if grid[(x+1+m) % m][(y-1+n) % n] & 1 == 1:
        live_count += 1

    if grid[(x-1+m) % m][(y+1+n) % n] & 1 == 1:
        live_count += 1
    if grid[(x-1+m) % m][(y-1+n) % n] & 1 == 1:
        live_count += 1

    return live_count


Followup:
- infinite grid (no border!)
cur_generation = {(i, j) for i, row in enumerate(board) for j, live in enumerate(row) if live}
ctr = collections.Counter((I, J)
                                         for i, j in live
                                         for I in range(i-1, i+2)
                                         for J in range(j-1, j+2)
                                         if I != i or J != j)

next_generation = {ij for ij in ctr if ctr[ij] == 3 or ctr[ij] == 2 and ij in live}
- really large grid!
- multi-thread / multi-process: no problem!
- map/reduce: split into squares, pass them with their own border, so that they don’t have to use internet to get data.


Text Editor oo design
Rope(data structure)

我一开始说要用char[][]。 但是給批评了好久...最后用了arraylist<arrayList<String>> 貌似...勉强通过了....然后...用什么储存..hightlight的...我一开始用hashset了..但是有个问题就是.delete的东西里面.刚好是hightlight的..那你怎么知道..你delete 的东西..也在hashset里面...所以.后来我用interval tree了.....他说...有道理多了....然后最后问了redo 和undo 怎么做...我用两个stack 储存operation.....

需要实现分页,编辑,以及undo和redo。


用什么数据结构来存这些输入进来的字符最有效。最后给出的是 list + array 的方法。。。


text editor,我先给了一个array的solution。后来时间不太多了,问我有没有更好的,我就说用binary tree,其实就是rope的那个实现。结构框架都和各个方法怎么来实现也都说了个大概。


insert(p), delete(p1, p2), highlight(p1, p2),redo/undo, save/load update, search
text editor需要insert,remove,highlight,需要想办法去index每次插入的object,原po说的interval tree应该就是index的方式吧。
关键点在于text打算怎么存
store highlight?
他要求三天后再load这个text,需要可以undo三天前的操作. save的时候 保存成xml类型之类的 把之前的操作也一起存下来


- What objects?
- Larget string.

- What ds?
- Rope

- What operation?
- Insert, delete, search, print <- index, concat, split

- What about highlight?

- add field ‘font’ in the internal nodes, split when necessary

- Undo/redo?

- Use two stacks, one for each, and make operations into objects


Third round
Debug guava



At least 4 functions need to rewrite, debug:
- put
- size
- clear
- clearall



// put
  public boolean put(@Nullable K key, @Nullable V value) {
    Collection<V> collection = map.get(key);
    if (collection == null) {
      collection = createCollection(key);
      if (collection.add(value)) {
        totalSize++;
        map.put(key, collection);
        return true;
      } else {
        throw new AssertionError("New Collection violated the Collection spec");
      }
    } else if (collection.add(value)) {
      totalSize++;
      return true;
    } else {
      return false;
    }
  }

  /**
   * Removes all values for the provided key.
   */
  private void removeValuesForKey(Object key) {
    Collection<V> collection = Maps.safeRemove(map, key);

    if (collection != null) {
      int count = collection.size();
      collection.clear();
      totalSize -= count;
    }
  }

  // get
  public Collection<V> get(@Nullable K key) {
    Collection<V> collection = map.get(key);
    if (collection == null) {
      collection = createCollection(key);
    }
    return wrapCollection(key, collection);
  }


Third Set
First round
LRU
Get
- illegal input
- update (key, value)

Set
- key existed — update
- new key
— enough space
— not enough space

Size

Fast
- in get, hash table to get value and move it to head
- in set, double linked list for quick modification
— move to head
— add to head
— delete from tail


Second round
Best Time to Buy and Sell Stock III

One dimension
- max_profit = array(n)
- max_profit[i] = max(max_profit[i], # day i is not involved in transaction, we’re using stat from previous day, or
                                  prices[i] - min_prices from [0 .. i-1] # stock sold on day i, buy on j from [0 .. i-1], max_minus_prices from [0 .. i-1])

K dimension (k transactions)
- max_profit = matrix[k * n], max profit till day i using UP to k transactions.
- max_profit[kk][i] = max(max_profit[kk][i-1], # same, not involved with day i
                                        max(prices[i] - prices[j] + max_profit[kk-1][j]) # One transaction bought on day j, sold on day i

                                                                                                               # plus max_profit[kk-1][j], on day j using k - 1 transactions

- where the underline part is computed multiple times, each time we can just use max_diff = max(max_diff, - prices[j] + max_profit[kk-1][j]) to save time.


Median of two sorted arrays

Test cases:
    def test_empty_array(self):
        self.assertEqual(self.solution.findMedianSortedArrays([], [1]), 1)
        self.assertAlmostEqual(
            self.solution.findMedianSortedArrays([], [1, 2]), 1.5)
        self.assertEqual(self.solution.findMedianSortedArrays([2], []), 2)
        self.assertEqual(self.solution.findMedianSortedArrays([1, 3], []), 2)

    def test_three_elements_left(self):
        self.assertEqual(self.solution.findMedianSortedArrays([2, 3], [1]), 2)
        self.assertEqual(self.solution.findMedianSortedArrays([1, 3], [2]), 2)

    def test_four_elements_left(self):
        self.assertEqual(
            self.solution.findMedianSortedArrays([2, 5], [1, 4]), 3)
        self.assertEqual(
            self.solution.findMedianSortedArrays([4, 5], [1, 2]), 3)

    def test_different_lengths(self):
        self.assertEqual(self.solution.findMedianSortedArrays(
            [1, 2, 2, 4, 5], [1, 4]), 2)
        self.assertEqual(self.solution.findMedianSortedArrays(
            [1, 2, 4, 5], [1, 2]), 2)
        self.assertEqual(self.solution.findMedianSortedArrays(
            [1, 2, 2, 4, 5], [1, 4, 5]), 3)
        self.assertEqual(self.solution.findMedianSortedArrays(
            [1, 2, 4, 5], [1, 2, 7]), 2)

    def test_two_median_relationship(self):
        self.assertEqual(self.solution.findMedianSortedArrays(
            [1, 2, 2, 4, 5], [1, 4, 5]), 3)
        self.assertEqual(self.solution.findMedianSortedArrays(
            [1, 2, 2, 4, 5], [1, 1, 5]), 2)
        self.assertEqual(self.solution.findMedianSortedArrays(

            [1, 2, 2, 4, 5], [1, 2, 5]), 2)

Algorithm:
    def find_kth_smallest(self, nums1, nums2, k):
        m, n = len(nums1), len(nums2)
        if m > n:
            return self.find_kth_smallest(nums2, nums1, k)

        if not nums1:
            return nums2[k - 1]

        if k == 1:
            return min(nums1[0], nums2[0])

        i = min(k / 2, m)
        j = min(k / 2, n)
        if nums1[i - 1] > nums2[j - 1]:
            return self.find_kth_smallest(nums1, nums2[j:], k - j)
        else:
            return self.find_kth_smallest(nums1[i:], nums2, k - i)

    def findMedianSortedArrays_v2(self, A, B):
        m, n = len(A), len(B)
        if m > n:
            A, B, m, n = B, A, n, m
        if n == 0:
            raise ValueError

        imin, imax, half_len = 0, m, (m + n + 1) / 2
        while imin <= imax:
            i = (imin + imax) / 2
            j = half_len - i
            if i < m and B[j - 1] > A[i]:
                # i is too small, must increase it
                imin = i + 1
            elif i > 0 and A[i - 1] > B[j]:
                # i is too big, must decrease it
                imax = i - 1
            else:
                # i is perfect

                if i == 0:
                    max_of_left = B[j - 1]
                elif j == 0:
                    max_of_left = A[i - 1]
                else:
                    max_of_left = max(A[i - 1], B[j - 1])

                if (m + n) % 2 == 1:
                    return max_of_left

                if i == m:
                    min_of_right = B[j]
                elif j == n:
                    min_of_right = A[i]
                else:
                    min_of_right = min(A[i], B[j])

                return (max_of_left + min_of_right) / 2.0


Third round
ATM oo design
- 设计interface
- 有基本的interface, 写implementation





Accounts:
- checking
- saving

Functions:
- withdraw
- deposit
- transfer
- inquiry
- setting

class ATM
class User
class Accounts



[/i][/i][/i][/i][/i][/i][/i][/i][/i]

本帖子中包含更多资源

您需要 登录 才可以下载或查看附件。没有帐号?注册账号

x

评分

参与人数 114大米 +935 收起 理由
yeesunch + 1 给你点个赞!
NewbieDave + 2 给你点个赞!
DeoNed + 2 总结非常详细!超级有用
wzmg + 1 给你点个赞!
jinloo + 1 很有用的信息!

查看全部评分


上一篇:阿妈粽两天丢欧诶一12/20
下一篇:口袋宝石一面面经

本帖被以下淘专辑推荐:

推荐
 楼主| z026 2017-1-13 16:05:44 | 只看该作者
全局:
再补充一点,为什么不方便看,我觉得自己还是有想注意格式的。。

大概就是:
- Behavioral
- 电面6题加答案
- onsite 三套,每套三轮,附答案

就是这样。。
回复

使用道具 举报

全局:
lz 跪求文件密码~~~
回复

使用道具 举报

推荐
daniel123 2020-9-10 12:45:55 | 只看该作者
全局:
楼主求问一下密码是什么
回复

使用道具 举报

🔗
luochenhuan 2016-12-21 20:42:13 | 只看该作者
全局:
patpat 第一场onsite就直接上hard的TS 能撑到下午很不容易了~

看到lz准备地这么仔细,只把所有面经看了一遍的自己感到很惭愧。。。。

面试这东西都是尽人事听天命 lz将来一定会有更好的offer的!

回复

使用道具 举报

🔗
tobebeyond 2016-12-21 20:53:50 | 只看该作者
全局:
请问2s会问很多os ood问题吗
回复

使用道具 举报

🔗
 楼主| z026 2016-12-22 00:29:52 | 只看该作者
全局:
luochenhuan 发表于 2016-12-21 20:42
patpat 第一场onsite就直接上hard的TS 能撑到下午很不容易了~

看到lz准备地这么仔细,只把所有面经看了 ...

谢谢,只能尽力啦。

我也想上来先来个低难度的先通关一次啊哭,没给机会没办法呀T T
回复

使用道具 举报

🔗
 楼主| z026 2016-12-22 00:30:55 | 只看该作者
全局:
chenqidi 发表于 2016-12-21 20:53
请问2s会问很多os ood问题吗

OOD的好像就面经里固定的那几道了。

剩下的要看下午match的组需要怎么样的人他们会问不同的问题。

评分

参与人数 1大米 +10 收起 理由
tobebeyond + 10 感谢分享!

查看全部评分

回复

使用道具 举报

🔗
点菜大司马 2016-12-22 00:51:31 | 只看该作者
全局:
我服。。。LZ太细致了。 hard work pays off.
回复

使用道具 举报

🔗
leixiang5 2016-12-22 01:02:16 | 只看该作者
全局:
楼主牛。 没见过比这个更详细了。楼主准备的这些肯定会帮到你面其他公司的
回复

使用道具 举报

🔗
YJLiGT 2016-12-22 04:50:38 | 只看该作者
全局:
楼主好人,会有好offer的,请问OA, 电面,onsite能只用Java吗,还是有的需要用C 或者 C++ 做, 如round : Reverse Polish Notation, 谢谢
回复

使用道具 举报

🔗
 楼主| z026 2016-12-22 05:00:59 | 只看该作者
全局:
YJLiGT 发表于 2016-12-22 04:50
楼主好人,会有好offer的,请问OA, 电面,onsite能只用Java吗,还是有的需要用C 或者 C++ 做, 如round : R ...

C++, Java, Python都有。

我用python写的,不是Java。。
回复

使用道具 举报

🔗
YJLiGT 2016-12-23 04:08:46 | 只看该作者
全局:
z026 发表于 2016-12-22 05:00
C++, Java, Python都有。

我用python写的,不是Java。。

好的,谢谢回复
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表