Sie sind auf Seite 1von 54

TODO List: 5

❌ Tree Traverse 5
❌ Max Heap, Min Heap using Priority Queue 5
❌ List data structure methods! 5
❌ Questions related to range, intervals!!! 5
系统设计: 6
https://soulmachine.gitbooks.io/system-design/content/cn/search-engine.html 6
http://systemdesigns.blogspot.com/2016/01/cassandra-vs-dynamo.html 6
[面试经验] LinkedIn Top10高频系统设计问题总结+讨论 6
高频top k 6
data stream, 内存有限,输出最大的K个数 6
top N exceptions in recent K time, 6
统计最近5min的request 6
Top k个shared links ++ 6
https://github.com/FreemanZhang/system-design/blob/master/linkedin/topk.md 6
top N issue. 巨大的数据怎么办 7
设计一个类似youtube的网站 7
设计linkedin Ads. 7
短链接 ++++++ 7
设计日历++ 7
设计亚麻购物界面 8
问已经有个sharing service 可以share 任何link。 ++ 8
设计一个日志系统 8
设计个service,处理push和pull请求。 9
delay scheduler. +++ 9
设计job推荐系统 9
设计news feed 9
KV store ++++ 9
如何判断friend ++ 9
如何sharding inverted index。 9
Design Monitoring System, 10
设计一个dashboard 10
地图 10
H2O 10
Blacklist IP 10
给你一个userID,返回能cover住这个user的全部advertisers。 10
设计一个单机的类 stream 的单写多读的系统 10
又是一个单机类 stream 单写多读系统 11
如何设计一个model判断一条信息是不是广告 11
设计一个可以查询数据的系统 11
Real time Content Delivery 11
多个server怎么解决global id unique的问题, 11
Union and Intersection of two sorted array 12
X 68. 12

Data Structure Design 12


✅❌ 716. Max Stack +++++++ 12
✅Sol 1. Three stacks 12
❌ Sol 2: Double Linked List + Map (not hash Map!) 13
✅380 Insert Delete GetRandom O(1) ++++++ 13
❌381 Insert Delete GetRandom O(1) - Duplicates allowed ++++++ 14
432 All O`one Data Structure 14
✅384 Shuffle an Array 16

Binary Search 16
✅❌ 272 Closest Binary Search Tree Value II +++++ 16
✅Sol 1. Convert BST to sorted array (in order traversal) 17
✅ Sol 2. During in-order traversal 18
❌ Sol 3. Two stacks. One storing larger than target, the other smaller than target. 18
❎69 Sqrt(x) +++++ 19
Variant: Input is float 20
❎34 Search for a Range +++ 20
❎❌367 Valid Perfect Square 20
❎Sol 1. Binary Search O(lgn) 20
❎Sol 2. Math arithmetic sequence O(sqrt n) 21

DP / Memorization 21
✅ 256 Paint House ++++ 21
✅ 265 Paint House II ++++ 21
✅Sol 1. Time O(NK), Space O(NK) 21
✅Sol 2. Time O(NK), Space O(1) 22
✅❌72 Edit Distance +++ 22
Variant: 23
❌464 Can I Win 23
✅❌ 361 Bomb Enemy 23
✅❌ 139 Word Break 24
DFS/BFS/Backtracking 25
✅ 200 Number of Islands ++++++++ 25
❌Variant 25
230 Kth Smallest Element in a BST +++++ 26
Sol 1: with help of additional vector 26
❌⭐ Sol 2: count k during in-order traversal 26
❌671 Second Minimum Node In a Binary Tree 27
❌ 366 Find Leaves of Binary Tree ++++++++ 27
❌ 339 Nested List Weight Sum 27
❌364 Nested List Weight Sum II ++ 28
606. Construct String from Binary Tree 28
❌46 Permutations I (no duplicates) ++ 28
❌47 Permutations II (with duplicates) ++ 29
❌254 Factor Combinations 29
❌113 Path Sum II 30

Tree, Graph 30
102 Binary Tree Level Order Traversal 30
✅❌ 103 Binary Tree Zigzag Level Order Traversal 30

Hashmap, Priority Queue 31


❌347 Top K Frequent Elements ++++ 31
❌170 Two Sum III - Data structure design 31
❌156 Binary Tree Upside Down ++ 32
Sol1. Iterative 32
❌❌❌Sol2. Recursive 32

Array 32
❌ 277 Find the Celebrity 33
Variant: 33
✅243 Shortest Word Distance 33
❌✅244 Shortest Word Distance II 34
53 Maximum Subarray 34
❌152 Maximum Product Subarray 34
❌235 Lowest Common Ancestor of a Binary Search Tree + 35
❌236. Lowest Common Ancestor of a Binary Tree + 35
Variant: has parent node! 35
Thread-safe Hashtable put get 实现 (multithreading) 36
N dimensional image volume 37
求两个linked list 是否 merge。+++ 37
❌282 Expression Add Operators 37
多维数组求和 37
516 Longest Palindromic Subsequence 37
322 Coin Change 37
698 Partition to K Equal Sum Subsets +++ 37
Variant 37
76 Minimum Window Substring +++ 37
❌ 721. Accounts Merge 38
341. Flatten Nested List Iterator +++ 38
flatten 4-direction doubly linked list 38
3 degree好友 39
设计一个支持produce h和o consume并生成h2o的class 39
找convex function的min 39
❌149 Max Points on a Line ++++ 39
39 Combination Sum ++ 40
297 Serialize and Deserialize Binary Tree +++ 40
205. Isomorphic Strings 40
349 Intersection of Two Arrays 40
606 Construct String from Binary Tree 40
实现 string replace 40
✅344 Reverse String 40
❌Variant 41
❌56 Merge Intervals ++ 41
57 Insert Interval 41
❌127 Word Ladder 41
Given number array and k, see if array could be divided to k buckets which all have same sum +++ 42
给一个array 和target,要找出所有subset, summary是target的。 42
给你一个int c, 返回boolean 表示是否可以有a^2 + b^2 = c^2 存在,a,b,c > 0 42
❌647 Palindromic Substrings 42
切匹萨,推导并总结出dp方程++ 42

Math 42
13. Roman to Integer ++++ 42
✅12. Integer to roman 42
✅ 238. Product of Array Except Self 43
187 Repeated DNA Sequences 43
Sol 1. Naive, a lot of storage 43
Sol 2. Compress! Last three bit of ACGT 43
地图 44
按权重返回随机数。 44
打印经过城市停车站的所有路线。 44
一个function实现计算器里的undo以及redo功能。 44
Someone’s Summary? 45
Bold Words in String 46

TODO List:

❌ Tree Traverse

❌ Max Heap, Min Heap using Priority Queue


In C++, default is Max heap (top is the largest).
In order to use min heap, two ways:
1. std::greater
std::priority_queue<​int​, std::vector​<int>​, ​std::greater​<int>​ > my_min_heap;

2.
struct​ compare {
bool​ ​operator​()(​const​ ​int​& l, c
​ onst​ i
​ nt​& r) { ​return​ ​l > r​; }
};
priority_queue<​int​,vector​<int>​, compare > pq;

❌ List data structure methods!


back() vs end(): end() returns pointer (iterator) past the last element, back() returns the content of the
last element.
begin vs front(): begin() returns pointer to the first element, front() returns the content of the first
element.

❌ Questions related to range, intervals!!!


系统设计:

https://soulmachine.gitbooks.io/system-design/content/cn/search-engine.html

http://systemdesigns.blogspot.com/2016/01/cassandra-vs-dynamo.html

[面试经验] LinkedIn Top10高频系统设计问题总结+讨论


http://www.1point3acres.com/bbs/forum.php?mod=viewthread&tid=294114
设计要写pseudo code, 每一步问的特别细

高频top k
不过我觉得可以考虑分bucket,然后通过消息队列去消费log, 这个是架构上的,存储上,算法上考虑到数据的波动
应该不会太大,可以缓存一波数据,从而请求时不用任何人计算。然后定期更新缓存。存储上可以分析数据量的
大小,考虑分布式内存数据库或者存本机内存,存本机内存可以考虑如何sharding,然后有个master集中处理的
结果。总之就是无非几点,跨机器如何通讯(消息队列),算法(基本的数据结构,能不能缓存),存储(本机内存,
分布式内存数据库,关系型数据库,nosql数据库,还是文件系统),然后就是如何负载均衡(一致性哈希?需不需
master?等等)。

data stream, 内存有限,输出最大的K个数

top N exceptions in recent K time,


基本是frequency estimation of streaming data,然后再讨论下如果要处理N台机器的log怎么做分布式。

统计最近5min的request

Top k个shared links ++


LinkedIn上的用户会用到很多shared links,然后要求设计个service来统计过去五分钟, 一个小时, 一天或着一
周里, 出现次数最多的Top k个shared links
http://davis.wpi.edu/xmdv/docs/EDBT11-diyang.pdf

https://github.com/FreemanZhang/system-design/blob/master/linkedin/topk.md
top N issue. 巨大的数据怎么办

设计一个类似youtube的网站
问了几个关于network latency, application I/O latency等等的小问题,然后设计一个类似youtube的网站
,画下基本架构

设计linkedin Ads.
每个user有一些attributes. 比如什么专业,什么level。每个广告有其针对的attribute。比如广告a针对
level 4以上的software engineer。设计系统当user登陆时根据他的attributes推送相应广告。基本就是一
个inverted index就搞定了,然后又聊了一些优化和follow up

短链接 ++++++
问题很多,需要处理single point failure 和scale
如果想统计过去 5mins, 1 hour request的tiny url要怎么保存 提取。
如何做load balance. 如何做主从备份。
自增id要加随机因子,不能被predict出来

设计日历++
基本上我就列了下面几个service 然后逐个说了一下如何实现的。
主要在讨论如何database里面的table
create event
check availability
add people event
event alert

https://www.jiuzhang.com/qa/5490/

这个问题比较大,在面试的时候我们可以先设计一个简单的Calendar,然后逐渐优化,正如这里所说
的​不考虑重复事件,用户少​。

1. 我们要看Calendar支持哪些功能

○ 列出年月日,当前这周,当前这个月根据当前的日期
○ 支持放一个event在calendar上,放入event上之后,你可以加入某人到这个event中,并
且给他发notification
○ 支持放一个周期性的event(如题目描述这个不需要考虑)
○ event来临前的提醒,比如前10分钟你需要发出提醒
○ 把events按照时间线列在calendar上
○ 以上是我们大概需要实现的功能,比如Google calendar功能非常丰富,实际上我们是不
需要在面试中一一列出来的,列出主要的即可
2. 开始设计table (也就是数据库的schema)
○ User profile 用户的基本信息table是需要的,存user id,user email(需要发邮件邀请加入event),

user nick

○ Events table 对于每一个被创建的event,我们需要有一个记录,这个event的title,时间(什么时候开始

,什么时候结束),description(event的大致描述),status (表示是否提醒过)等等

○ Attend table, 一旦一个user进入一个event,那么我们就创建​<event_id, user_id>​这样一个关联,那

么对于这个event有哪些人参数我们可以做一个query得到,同样的,一个人参与了哪些events,也可

以用一个query得到。当然你也可以把参与的人存入Events table当中,不需要这个关联。

3. storage 存储介质:
○ 我们可以选择SQL 也可以选择NOSQL来存(正如题目描述中的,user并不是很多)

4. 实现notify功能
○ 我们可以实现一个消息队列,把快要开始的而且status是没有提醒过的events丢进消息队列中,消息

队列的头部负责查看是否刚好是十分中,如果是的,那么就推一个notification给用户,提醒到event马

上就要开始了。

5. 实现邀请功能
○ 一旦你把一些人加入到这个event中,那么我们给用户一个提示,是否要发邮件给这些人,所以我们还

需要实现一个邮件发送的功能。

设计亚麻购物界面

问已经有个sharing service 可以share 任何link。 ++


怎么设计另一个service 用来统计每五分钟 一小时 和一天的 每个不同的link share的次数 不用特别精确

设计一个日志系统
储存其他服务生成的日志,支持关键字搜索。一直问日志应该怎么传输.
传输感觉应该是用Kafka?支持关键字搜索这个应该就是扯一下MapReduce,Inverted Index吧?
设计个service,处理push和pull请求。
假设每个push请求都有个unique incremental ID和它的payload,每个pull请求都有个id作为它的参数;
对于pull请求,要返回所有push请求中ID最大的且不大于pull id的请求的payload(如果push 1, x, push
4, y, pull 5返回y)

delay scheduler. +++


以及threadpool
https://soulmachine.gitbooks.io/system-design/content/cn/task-scheduler.html
设计是用min heap存所有任务开始的时间,然后在添加任务或者到下一个任务开始的时候唤醒dispatch线程,根
据堆顶任务的时间是否是当前时间决定是否执行任务。

设计job推荐系统

设计news feed

KV store ++++
https://soulmachine.gitbooks.io/system-design/content/cn/key-value-store.html
https://www.jiuzhang.com/qa/4818/
V可以很大,K可以进memory,memory中只能使用hashtable这种data structure;可以使用文件系统存KV pair
,但是文件系统只支持delete,create,append,seek,read
每一个put的带一个microsecond的time to live。ttl用circular buffer
key可以在memory,value太大需要disk,只讨论单机。file system只支持file creation deletion,random read,
file content append,不支持override, random delete。
文件系统是类似 HDFS 一样的
Value要存到disk上问得非常细节,例如 写内存与写磁盘的先后顺序,逐条 log 演示做 log compaction 的步骤

如何判断friend ++
friend of friend,friend of friend of friend,followup如何shard data提高效率
设计系统查询A和B 是否为1度好友,2度好友和3度好友
https://www.quora.com/How-does-LinkedIn-compute-mutual-friend-pathways-so-quickly

如何sharding inverted index。


file-》关键词是正向的。按HDFS和Dynamo两种答的。 coding blocking queue。
http://code972.com/blog/2013/10/417-building-a-distributed-search-engine-refactoring-story-part-2
Design Monitoring System,
比如每台机器的CPU pct,要求支持UI 和alert

设计一个dashboard
dashboard是一个地图,当有新用户注册账号时,需要实时在dashboard上显示用户位置?
follow up:前端用什么library?(d3.js),需要向前端发送哪些数据?(经纬度或者geohash),push vs pull?怎
么实现push service?(消息队列)?怎么测试?

地图
上面有很多点, 每个点是个object, x, y 坐标都给了, 比如{x: 5, y: 5}
已知 包含所有点的 array, 某一个点,和半径d, 写一个function 返回到这个点的距离小于或等于d 的所有点。怎么
优化。我当时答得是把整个地图分成小的区域,每一小块2d的正方形。然后找这个点所在的方块和周围的几个方
块。这样就不用遍历地图里所有的点了。

H2O
水是2个h一个o组成. 好多的thread 要多call func_h() 或者 func_o() call的时候,产生一个原子(h或者o),如果前
面已经有thread提供过h 还有o,就继续,产生一个h2o 如果没有足够的h和o,wait()
http://www.1point3acres.com/bbs/forum.php?mod=viewthread&tid=295838

Blacklist IP
这个list会增加删减条目,每一个request都会来lookup这个list。

给你一个userID,返回能cover住这个user的全部advertisers。
这里假设用户注册的时候你知道他的location data(longtitude,lattitude)这个是固定的,每个advertiser也有
location data,除去longtigude,lattitude,还有一个radius,表示这个advertiser的覆盖范围。先讨论算法实现以及算
法优化,然后就是基本system design讨论,如何存储,如果提高性能等等。

设计一个单机的类 stream 的单写多读的系统


细节我忘了……但是重点是如何做好 thread-safe。这一类题目就是对并发编程的考察,关键就是加锁(如果你
懂 lock-free 的实现,也可以扯扯,但是我认为面试官不会期望你能给出一个 lock-free 的解答)。简单的一个
global lock 是肯定不行的,性能太差。最好的参考资料其实就是各个并发编程的库,例如 java.util.concurrent。
运用适当的加锁技巧,达到面试官的预期就 OK。
http://wanglizhi.github.io/2016/08/06/Java-Concurrency/
又是一个单机类 stream 单写多读系统
生产者会不定期地生成一个数值,消费者们不定期地通过 geAvg5min() 获取过去5分钟内生成的数值的平均值

如何设计一个model判断一条信息是不是广告

设计一个可以查询数据的系统
我就提出直接用LAMP。然后就问如果增加了Query的QPS怎么办,增加了input的数据量怎么办,我就提到了用
sharding啦,Load Balancer啦,Kafka啦之类的,然后分析trade off和计算了下需要的机器数量
Real time Content Delivery

多个server怎么解决global id unique的问题,
专门用一个server去分配id被否定,会有single point failure,后来加入server id做prefix,就好
https://soulmachine.gitbooks.io/system-design/content/cn/distributed-id-generator.html
Union and Intersection of two sorted array
http://blog.csdn.net/pplin/article/details/60574397

X 68.

Data Structure Design


✅❌ 716. Max Stack +++++++
http://wxx5433.github.io/max-stack.html

✅​Sol 1. Three stacks


stack<int> main_stack, max_stack, ​temp_stack;
/** initialize your data structure here. */
MaxStack() {}
void push(int x) {
main_stack.push(x);
if (​max_stack.empty()​ || x > max_stack.top()) {max_stack.push(x);}
else max_stack.push(max_stack.top());
}
int pop() {
int ret = main_stack.top();
max_stack.pop();
main_stack.pop();
return ret;
}
int top() {return main_stack.top();}
int peekMax() {return max_stack.top();}
int ​popMax()​ {
int max_val = max_stack.top();
while (main_stack.top() != max_val) {
max_stack.pop();
temp_stack.push(main_stack.top());
main_stack.pop();
}
main_stack.pop();
max_stack.pop();
while (!temp_stack.empty()) {
main_stack.push(temp_stack.top());
if (​max_stack.empty()​ || temp_stack.top() > max_stack.top()) {
max_stack.push(temp_stack.top());
} ​//往回放的时候依然需要maintain max stack
else max_stack.push(max_stack.top());
temp_stack.pop();
}
return max_val;
}

❌ ​Sol 2: Double Linked List + Map (not hash Map!)


​map​<int, vector<​list<int>::iterator​>> m_map;
​list​<int> m_stk;
MaxStack() { }
void push(int x) {
m_stk.push_back(x);
m_map[x].push_back(​--m_stk.end()​);
}
int pop() {
int val = m_stk.back();
m_stk.pop_back();
m_map[val].pop_back();
if (m_map[val].empty()) m_map.​erase​(val); ​//must erase to track existing max!
return val;
}
int top() { return m_stk.back();}
int peekMax() {return m_map.​rbegin()->first​;}
int popMax() {
int ​val = m_map.rbegin()->first;
m_stk.erase(m_map[​val​].​back​());
m_map[val].pop_back();
if (m_map[val].empty()) {m_map.erase(val);}
return val;
}

✅380 Insert Delete GetRandom O(1) ++++++


vector<int> nums; ​//store the numbers, can return a random one in O(1) time
​unordered_map<int, int> m_map​; /​/​key:​ integer, ​value:​ index in the nums vector!!!
/** Initialize your data structure here. */
RandomizedSet() {}
/** Inserts a value to the set. Returns ​true​ if the set did ​not​ already contain the specified
element. */
bool insert(int val) {
if (m_map.find(val) != m_map.end()) return false;
nums.push_back(val);
m_map[val] = nums.size() - 1;
return true;
}
/** Removes a value from the set. Returns ​true​ if the set contained the specified element. */
bool remove(int val) {
if (m_map.find(val) == m_map.end()) ​return​ false;
int idx = m_map[val];
int end_val = nums[nums.size()-1];
nums[idx] = end_val;
nums.pop_back();​//Don't forget!!!
m_map[end_val] = idx;
m_map.​erase​(val); ​//also need to erase val!
​return​ true;
}
/** Get a random element from the set. */
int getRandom() { return nums[rand() % nums.size()];}
};

❌381 Insert Delete GetRandom O(1) - Duplicates allowed ++++++


vector<pair<int, int>> nums; ​//store the ​number - index pair
unordered_map<int, vector<int>> m_map; ​//key is the value of the integer, value is their
indices in the m_map[val] vector!!!
/** Initialize your data structure here. */
RandomizedCollection() { }
/** Inserts a value to the collection. Returns true if the collection did not already contain
the specified element. */
bool insert(int val) {
bool result = (m_map.find(val) == m_map.end());
nums.push_back({val, ​m_map​[val].​size()​});
m_map[val].push_back(nums.size() - 1);
return result;
}
/** Removes a value from the collection. Returns true if the collection contained the
specified element. */
bool remove(int val) {
​if ​(m_map.find(val) == m_map.end()) ​return​ false;
auto ​last ​= nums.back(); ​//need to swap last with val.
​m_map[last.first][last.second]​ = m_map[val].​back();
nums[m_map[val].back()] = last;
m_map[val].pop_back();
​if​(m_map[val].empty()) { m_map.erase(val); }
​nums.pop_back();
​return​ true;
}
/** Get a random element from the collection. */
int getRandom() {return nums[rand() % nums.size()].​first​;}

​432 All O`one Data Structure


class AllOne {
struct Row {
list<string> strs;
int val;
Row(const string &s, int x) : strs({s}), val(x) {}
};
unordered_map<string, pair<​list<Row>::iterator​, ​list<string>::iterator​>> strmap;
list<Row> matrix;
/** Initialize your data structure here. */
AllOne() {}
/** Inserts a new key <Key> with value 1. Or increments an existing key by 1. */
void ​inc​(string key) {
if (strmap.find(key) == strmap.end()) { ​//key do not exist
if (matrix.empty() || matrix.back().val != 1) { ​//no row with val 1
auto newRow = matrix.emplace(matrix.end(), key, 1);
strmap[key] = make_pair(newRow, newRow->strs.begin());
}
else { ​ //with row val == 1
auto ​newRow ​= --matrix.end();
newRow->strs.push_front(key);
strmap[key] = make_pair(newRow, newRow->strs.begin());
}
}
else { ​//key already there, need to move to the next row
auto row = strmap[key].first;
() auto col = strmap[key].second;
auto lastRow = row;
lastRow --;
if (lastRow == matrix.end() || lastRow->val != row->val + 1) {
auto newRow = matrix.emplace(row, key, row->val + 1);
strmap[key] = make_pair(newRow, newRow->strs.begin());
}
else {
auto newRow = lastRow;
newRow->strs.push_front(key);
strmap[key] = make_pair(newRow, newRow->strs.begin());
}
row->strs.erase(col);
if (row->strs.empty()) { matrix.erase(row); }
}
}
​/** Decrements an existing key by 1. If Key's value is 1, remove it from the data structure.
*/
void ​dec​(string key) {
if (strmap.find(key) == strmap.end()) //if not exist, do nothing
return;
auto row = strmap[key].first;
auto col = strmap[key].second;
if (row->val == 1) { //check if val is 1
row->strs.erase(col);
if (row->strs.empty()) matrix.erase(row);
strmap.erase(key);
return;
}
auto nextRow = row;
nextRow ++;
if (nextRow == matrix.end() || nextRow->val != row->val - 1) {
auto newRow = matrix.emplace(nextRow, key, row->val - 1);
strmap[key] = make_pair(newRow, newRow->strs.begin());
}
else {
nextRow->strs.push_front(key);
strmap[key] = make_pair(nextRow, nextRow->strs.begin());
}
row->strs.erase(col);
if (row->strs.empty()) matrix.erase(row);
}
/** Returns one of the keys with maximal value. */ //can use begin()->
string ​getMaxKey​() { return matrix.empty() ? "" : matrix.front().strs.front();}
/** Returns one of the keys with Minimal value. */
string ​getMinKey​() {return matrix.empty() ? "" : matrix.back().strs.front();}
};

341. Flatten Nested List Iterator +++


stack<NestedInteger> m_stack;
NestedIterator(vector<NestedInteger> &nestedList) {
for (int i = nestedList.size() - 1; i >= 0; i--){m_stack.push(nestedList[i]);}
}
int next() {
int ret = m_stack.top().​getInteger​();
m_stack.​pop​();
return ret;
}
bool hasNext() {
while (!m_stack.empty()){
NestedInteger cur = m_stack.top();
​if ​(cur.isInteger()) {​return​ ​true​;}
m_stack.pop();
ve​ctor<NestedInteger>​ m_list = cur.getList();
for (int j = m_list.size() - 1; j >= 0; ​j​--​) {m_stack.push(m_list[j]);}
}
return false;
}

✅384 Shuffle an Array


vector<int> curr, origin;
int size;
Solution(vector<int> nums) {
curr = nums;
origin = nums;
size = nums.size();
}
/** Resets the array to its original configuration and return it. */
vector<int> reset() {
curr = origin;
return origin;
}
/** Returns a random shuffling of the array. */
vector<int> shuffle() {
for (int i = 0; i < size; i++) ​swap​(curr[i], curr[rand() % size]);
return curr;
}

Binary Search
✅​❌​ 272 Closest Binary Search Tree Value II +++++
http://www.cnblogs.com/grandyang/p/5247398.html

✅​Sol 1. Convert BST to sorted array (in order traversal)


vector<int> res, v;
//in order traversal, put values into v
inOrder(root, v);
//find closest idx
int idx = 0;
double diff = numeric_limits<double>::max();
for (int i = 0; i < v.size(); i++) {
if (abs(v[i] - target) <= diff) {
diff = abs(v[i] - target);
idx = i;
}
}
//expand to find the k closest
int left = idx - 1, right = idx + 1;
for (int i = 0; i < k; i++) {
res.push_back(v[idx]);
if (left >= 0 && right < v.size()) {
if (abs(v[left] - target) < abs(v[right] - target)) {
idx = left;
left --;
}
else {
idx = right;
right ++;
}
}
else if (left >= 0) {
idx = left;
left --;
}
else if (right < v.size()) {
idx = right;
right ++;
}
}
return res;
}
void ​inOrder​(TreeNode* root, vector<int>& v) {
if (!root) return;
inOrder(root->left, v);
v.push_back(root->val);
inOrder(root->right, v);
}

✅ ​Sol 2. During in-order traversal


当遍历到一个节点时,如果此时结果数组不到k个,我们直接将此节点值加入res中,如果该节点值和目标值的差值的
绝对值小于res的首元素和目标值差值的绝对值,说明当前值更靠近目标值,则将首元素删除,末尾加上当前节点值
,反之的话说明当前值比res中所有的值都更偏离目标值,由于中序遍历的特性,之后的值会更加的遍历,所以此时
直接返回最终结果即可
​ vector<int> closestKValues(TreeNode* root, double target, int k) {
deque<int> res;
inOrder(root, res, target, k);
vector<int> ret;
for (auto ele : res) {
ret.push_back(ele);
}
return ret;
}
void inOrder(TreeNode* root, deque<int>& res, double target, int k) {
if (!root) return;
inOrder(root->left, res, target, k);
if (res.size() < k) {res.push_back(root->val);}
else {
if (abs(root->val - target) < abs(res[0] - target)) {
res.pop_front();
res.push_back(root->val);
}
else return;
}
inOrder(root->right, res, target, k);
}

❌​ Sol 3. Two stacks. One storing larger than target, the other smaller than target.
vector<int> closestKValues(TreeNode* root, double target, int k) {
vector<int> ret;
stack<TreeNode​*​> pre, suc;
while (root) {
if (root->val <= target) {
pre.push(root);
root = root->right;
}
else {
suc.push(root);
root = root->left;
}
}
while (k--) {
if (suc.empty() || !pre.empty() && target - pre.top()->val < suc.top()->val - target)
{
ret.push_back(pre.top()->val);
getPredessor(pre);
}
else {
ret.push_back(suc.top()->val);
getSucessor(suc);
}
}
return ret;
}
void getPredessor(stack<TreeNode*> &pre) {
TreeNode* t = pre.top();
pre.pop();
if (t->left) {
pre.push(t->left);
while (pre.top()->right) {
pre.push(pre.top()->right);
}
}
}
void getSucessor(stack<TreeNode*> &suc) {
TreeNode* t = suc.top();
suc.pop();
if (t->right) {
suc.push(t->right);
while (suc.top()->left) {
suc.push(suc.top()->left);
}
}
}

❎​69 Sqrt(x) +++++


int mySqrt(int x) {
​uint64_t​ left = 1, right = x;
​while ​(left + 1 < right) {
int mid = left + (right - left) / 2;
​if ​(​mid > x / mid​) right = mid;
​else if​ (mid < x / mid) left = mid;
​else ​ ​return ​mid;
}
​if ​(right * right > x) ​return ​left;
​return ​right;
}

Variant: Input is float

❎34 Search for a Range +++


vector<int> searchRange(vector<int>& nums, int target) {
if (nums.size() == 0) { return vector<int>{-1, -1};}
int leftbound, rightbound;
int left = 0, right = nums.size() - 1;
while (left + 1 < right) { ​//like find the first element
int mid = left + (right - left) / 2;
if (nums[mid] ​>=​ target) { right = mid;}
else if (nums[mid] ​<​ target) { left = mid;}
}
if (nums[​left​] == target) { leftbound = left; }
else if (nums[right] == target) { leftbound = right; }
else { ​return ​vector<int>{-1, -1};} ​//if can't find, return [-1, -1]
left = ​leftbound​, right = nums.size() - 1;​//then find the last element
while (left + 1 < right) {
int mid = left + (right - left) / 2;
if (nums[mid] ​>​ target) {right = mid;}
else if (nums[mid] ​<=​ target) {left = mid;}
}
if (nums[right] == target) { rightbound = right;}
else { rightbound = left;}
return vector<int>{left​bound​, right​bound​};
}
❎​❌​367 Valid Perfect Square

❎​Sol 1. Binary Search O(lgn)


bool isPerfectSquare(int num) {
​uint64_t ​left = 1, right = num / 2;
while (left + 1 < right) {
​uint64_t ​mid = left + (right - left) / 2;
​uint64_t ​mid_squared = mid * mid;
if (mid_squared < num) left = mid;
else if (mid_squared > num) right = mid;
else return true;
}
​uint64_t ​left_squared = left * left;
​uint64_t ​right_squared = right * right;
if (left_squared == num || right_squared == num) return true;
return false;
}

❎​Sol 2. Math arithmetic sequence O(sqrt n)


bool isPerfectSquare(int num) {
int n = 1;
while (num > 0) {
num -= n;
n += 2;
}
if (num == 0) return true;
return false;
}

DP / Memorization
✅ 256 Paint House ++++
int minCost(vector<vector<int>>& costs) {
if (!costs.size()) {return 0;}
for (int i = 1; i < costs.size(); i++) {
costs[i][0] += min(costs[i - 1][1], costs[i - 1][2]);
costs[i][1] += min(costs[i - 1][0], costs[i - 1][2]);
costs[i][2] += min(costs[i - 1][1], costs[i - 1][0]);
}
return min(costs[costs.size() - 1][0], min(costs[costs.size() - 1][1], costs[costs.size()
- 1][2]));
}
✅ 265 Paint House II ++++

✅​Sol 1. Time O(NK), Space O(NK)


int minCostII(vector<vector<int>>& costs) {
int m = costs.size();
if (m == 0) ​return ​0;
int n = costs[0].size();
if (n == 0) ​return ​0;
int min1 = -1, min2 = -1;
for (int i = 0; i < m; i++) {
int last1 = min1, last2 = min2;
min1 = -1;
min2 = -1;
for (int j = 0; j < n; j++) {
if (j != last1) {costs[i][j] += last1 < 0 ? 0 : costs[i - 1][​last1​];}
else {costs[i][j] += ​last2 ​< 0 ? 0 : costs[i - 1][​last2​];}
if (min1 < 0 || costs[i][j] < costs[i][min1]) {
min2 = min1;
min1 = j;
}
else if (min2 < 0 || costs[i][j] < costs[i][min2]) {min2 = j;}
}
}
return costs[m - 1][min1];
}

✅​Sol 2. Time O(NK), Space O(1)


int minCostII(vector<vector<int>>& costs) {
int m = costs.size();
if (m == 0) ​return ​0;
int n = costs[0].size();
if (n == 0) ​return ​0;
int min1 = 0, min2 = 0, ​idx ​= -1; ​//min1, min2: ​previous ​row mins
for (int i = 0; i < m; i++) {
int ​m1 ​= INT_MAX, ​m2 ​= m1, i
​ d1 ​= -1;​ //m1, m2: ​current ​row mins
for (int j = 0; j < n; j++) {
int cost = costs[i][j] += (j == idx ? ​min2 ​: ​min1​);
if (cost < m1) {
m2 = m1;
m1 = cost;
id1 = j;
}
else if (cost < m2) { m2 = cost;}
}
min1 = m1, min2 = m2, ​idx = id1;
}
return min1;
}

✅❌72 Edit Distance +++


int minDistance(string word1, string word2) {
vector<vector<int>> dp(word1.size()​+1​, vector<int>(word2.size()​+1​, INT_MAX));
for (int i = 0; i <= word2.size(); i++) {​dp[0][i] = i;​}
for (int i = 0; i <= word1.size(); i++) {​dp[i][0] = i;​}
for (int i = 1; i <= word1.size(); i++) {
for (int j = 1; j <= word2.size(); j++) {
dp[i][j] = min(dp[i][j], ​dp[i][j - 1] + 1​);
dp[i][j] = min(dp[i][j], ​dp[i - 1][j] + 1​);
if (word1[i - 1] == word2[j - 1]) {
dp[i][j] = min(dp[i][j], ​dp[i - 1][j - 1]​);}
else{dp[i][j] = min(dp[i][j], ​dp[i - 1][j - 1] + 1​); }
}
}
return dp[word1.size()][word2.size()];
}

Variant:
❌❌​edit distance to palindrome,给一个string,变成palindrome的edit distance是多少 (not in leetcode?)

698 Partition to K Equal Sum Subsets ++++

Sol1. Recursive
bool dfs(vector<int> &nums, int idx, vector<int> &sums, int n, int &k, int &sum) {
//39, 37, 23, 23, 12, 6, 4, 3, 2, 1
if (n == idx) {return true;}
for (int i = 0; i < k; i++) {
if (sums[i] + nums[idx] > sum) {continue;}
sums[i] += nums[idx];
if (dfs(nums, idx + 1, sums, n, k, sum)) {return true;}
sums[i] -= nums[idx];
}
return false;
}
bool canPartitionKSubsets(vector<int>& nums, int k) {
int sum = 0;
for (int i : nums) {sum += i;}
if (sum % k != 0) {return false;}
sum /= k;
sort(nums.begin(), nums.end());
reverse(nums.begin(), nums.end());
vector<int> sums(k);//K buckets to store the values
return dfs(nums, 0, sums, nums.size(), k, sum);
}

Sol2. DP. Can’t figure out


如果只要combination的个数,应该就是背包问题了。HOW!!!

​❌​464 Can I Win


bool canIWin(int maxChoosableInteger, int desiredTotal) {
int used = 0;
unordered_map<int, bool> m_map;
if (maxChoosableInteger >= desiredTotal) {return true;}
if (maxChoosableInteger * (maxChoosableInteger + 1) / 2 < desiredTotal) {return false;}
return canWin(maxChoosableInteger, desiredTotal, used, m_map);
}
bool canWin(int length, int total, int used, unordered_map<int, bool>& m_map) {
if (m_map.find(used) != m_map.end()) {return m_map[used];}
for (int i = 0; i < length; i++) {
int cur = (1 << i);
if ((cur & used) == 0) {
if (total <= i + 1 || !canWin(length, total - (i + 1), used | cur, m_map)) {
m_map[used] = true;
return true;
}
}
}
m_map[used] = false;​//for memorization
return false;
}

✅❌ 361 Bomb Enemy


题目很长,大概意思是一个游戏里的2D平面分布了一些点,每个点带有一个分值。用枪去射,每射到一个点则
当前点横竖相连的所有其他点都会被干掉。问最少射多少枪可以去掉所有的点,好像是这样,记不太清,可能还
加点别的要求。题目太长一开始没理解好意思,磨蹭了一点时间。followup是每次射击一个点时,所有相连点中
分值比它高的点可以存活,低的则干掉。问最多可以射多少次把全部点干掉。
int maxKilledEnemies(vector<vector<char>>& grid) {
int m = grid.size();
if (m == 0) { return 0;}
int n = grid[0].size();
if (n == 0) { return 0;}
vector<vector<int>> up(m, vector<int>(n, 0));
vector<vector<int>> down(m, vector<int>(n, 0));
vector<vector<int>> left(m, vector<int>(n, 0));
vector<vector<int>> right(m, vector<int>(n, 0));
for (int j = 0; j < n; j++) {if (grid[0][j] == 'E') {up[0][j] = 1;}}
for (int i = 1; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 'E') { up[i][j] = up[i - 1][j] + 1;}
else if (grid[i][j] == '0') {up[i][j] = up[i - 1][j];}
else {up[i][j] = 0;}
}
}
for (int j = 0; j < n; j++) { if (grid[m - 1][j] == 'E') {down[m - 1][j] = 1;}}
for (int i = m - 2; i >= 0; i--) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 'E') {down[i][j] = down[i + 1][j] + 1;}
else if (grid[i][j] == '0') {down[i][j] = down[i + 1][j];}
else {down[i][j] = 0;}
}
}
for (int i = 0; i < m; i++) { if (grid[i][0] == 'E') {left[i][0] = 1;}}
for (int j = 1; j < n; j++) {
for (int i = 0; i < m; i++) {
if (grid[i][j] == 'E') {left[i][j] = left[i][j - 1] + 1;}
else if (grid[i][j] == '0') {left[i][j] = left[i][j - 1];}
else {left[i][j] = 0;}
}
}
for (int i = 0; i < m; i++) {if (grid[i][n - 1] == 'E') { right[i][n - 1] = 1;}}
for (int j = n - 2; j >= 0; j--) {
for (int i = 0; i < m; i++) {
if (grid[i][j] == 'E') {right[i][j] = right[i][j + 1] + 1;}
else if (grid[i][j] == '0') {right[i][j] = right[i][j + 1];}
else {right[i][j] = 0;}
}
}
int ret = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == '0') {ret = max(ret, up[i][j] + down[i][j] + right[i][j] +
left[i][j]);}
}
}
return ret;
}

✅❌ 139 Word Break


bool wordBreak(string s, vector<string>& wordDict) {
if (s.length()==0) return false;
unordered_set<string> m_dict;
for (string word : wordDict) {m_dict.insert(word);}
vector<bool> dp(s.length() ​+ 1​, false);
dp[0] = true;
for (int i = 1; i <= s.length(); i++) {
for (int j = i - 1; j >= 0; j--) {
if (dp[j]) {
if (m_dict.find(s.substr(j, i - j)) != m_dict.end()) {
dp[i] = true;
break;
}
}
}
}
return dp[s.length()];
}

切匹萨,推导并总结出dp方程++
dp[0] = 1, dp[n] = dp[n - 1] + n
x(n) =n (n + 1) / 2 + 1

322 Coin Change


int coinChange(vector<int>& coins, int amount) {
//dp[i] -> minimal number of coins required to get amount i
//dp[i] = min(dp[i - coins[j]] + 1)
vector<uint64_t> dp(amount + 1, INT_MAX);
dp[0] = 0;
for (int i = 1; i <= amount; i++) {
for (int j = 0; j < coins.size(); j++) {
if (coins[j] <= i) {​dp[i] = min(dp[i], dp[i - coins[j]] + 1)​;}
}
}
return dp[amount] == INT_MAX ? -1 : dp[amount];
}

516 Longest Palindromic Subsequence


bool dfs(vector<int> &nums, int idx, vector<int> &sums, int n, int &k, int &sum) {
//39, 37, 23, 23, 12, 6, 4, 3, 2, 1
if (n == idx) {return true;}
for (int i = 0; i < k; i++) {
if (sums[i] + nums[idx] > sum) {continue;}
sums[i] += nums[idx];
if (dfs(nums, idx + 1, sums, n, k, sum)) {return true;}
sums[i] -= nums[idx];
}
return false;
}
bool canPartitionKSubsets(vector<int>& nums, int k) {
int sum = 0;
for (int i : nums) {sum += i;}
if (sum % k != 0) {return false;}
sum /= k;
sort(nums.begin(), nums.end());
reverse(nums.begin(), nums.end());
vector<int> sums(k);
return dfs(nums, 0, sums, nums.size(), k, sum);
}

❌647 Palindromic Substrings


int countSubstrings(string s) {
int res = 0;
for (int i = 0; i < s.length(); i++) {
for (int j = 0; i - j >= 0 && i + j < s.length() && s[i - j] == s[i + j]; j++) {
res ++; //aba cabac
}
for (int j = 0; ​i-j -1 >= 0​ && i + j < s.length() && s[i - j - 1] == s[i + j]; j++) {
res ++; //aa baab cbaabc
}
}
return res;
}

DFS/BFS/Backtracking
✅​ ​200 Number of Islands ++++++++
int numIslands(vector<vector<char>>& grid) {
if (grid.size() == 0) return 0;
if (grid[0].size() == 0) return 0;
int res = 0;
for (int i = 0; i < grid.size(); i++) {
for (int j = 0; j < grid[0].size(); j++) {
if (grid[i][j] == '1') {
res += 1;
dfs(grid, i, j);
}
}
}
return res;
}
void dfs(vector<vector<char>>& grid, int x, int y) {
​grid[x][y] = '0';
if (x > 0 && grid[x - 1][y] == '1')
dfs(grid, x - 1, y);
if (x < grid.size() - 1 && grid[x + 1][y] == '1')
dfs(grid, x + 1, y);
if (y > 0 && grid[x][y - 1] == '1')
dfs(grid, x, y - 1);
if (y < grid[0].size() - 1 && grid[x][y + 1] == '1')
dfs(grid, x, y + 1);
}

❌​Variant
完了改成求山谷数量,意思就是说二维数组里的整数值代表高度,求有几个local的最小值。举个例子,比如有一
个3X3的矩阵是matrix = [[1,2,0],[3,1,0],[-1,0,2]], 那么matrix[2][0]这个-1是一个山谷,右上角的两个上下连着的0
也是一个山谷。超出矩阵范围的坐标认为是有无限大的数。所以最后返回3.

230 Kth Smallest Element in a BST +++++

Sol 1: with help of additional vector


vector<int> v_ordered;
int kthSmallest(TreeNode* root, int k) {
in_order(root);
int sz = v_ordered.size();
return v_ordered[k - 1];
}
void in_order(TreeNode* root) {
if (!root) return;
in_order(root->left);
v_ordered.push_back(root->val);
in_order(root->right);
}

❌​⭐ Sol 2: count k ​during in-order traversal


int ret;
int kthSmallest(TreeNode* root, int k) {
helper(root, k);
return ret;
}
void helper(TreeNode* root, int &k) {
if (!root) ​return​;
helper(root->left, k);
​if ​(--k == 0) {
ret = root->val;
​return​;
}
​else helper(root->right, k);
}
讨论了时间空间复杂度啥的,小哥拓展了一些,比如修改树的条件,加上parent指针神马的。没怎么写代码。第
二问具体记不太清了,不过是梨眗里以善舅(139?)这种字符串查找之类的题目.
烙印一个人面,说了递归做法,说别这么做,想想别的,我心里想哪那么多屁,好吧dfs和bfs的都说了,问哪个
行就写哪个,答随便,就写了bfs的,不可能有问题,又问复杂度,也都答了

❌​671 Second Minimum Node In a Binary Tree


each node in this tree has exactly ​two​ or ​zero​ sub-node. If the node has two sub-nodes, then this node's value is the
smaller value among its two sub-nodes.
int min;
int ret = INT_MAX;
int findSecondMinimumValue(TreeNode* root) {
min = root->val;
dfs(root);
return ret == INT_MAX ? -1 : ret;
}
void dfs(TreeNode* root) {
if (!root) return;
if (root->val < ret && root->val > min) ret = root->val;
else if (root->val == min) {
dfs(root->left);
dfs(root->right);
}
}

❌ 366 Find Leaves of Binary Tree ++++++++


int dfs(TreeNode* root, vector<vector<int>>& ret) {
if (!root) return 0;
int level = max(dfs(root->left, ret), dfs(root->right, ret)) + 1;
if (​level > ret.size​()) {ret.push_back(vector<int>());}
ret[level - 1].push_back(root->val);
return ​level​;
}
vector<vector<int>> findLeaves(TreeNode* root) {
vector<vector<int>> ret;
dfs(root, ret);
return ret;
}
❌ 339 Nested List Weight Sum
* // Return true if this NestedInteger holds a single integer, rather than a nested list.
* bool isInteger() const;
* // Return the single integer that this NestedInteger holds, if it holds a single integer
* // The result is undefined if this NestedInteger holds a nested list
* int getInteger() const;
* // Return the nested list that this NestedInteger holds, if it holds a nested list
* // The result is undefined if this NestedInteger holds a single integer
* const vector<NestedInteger> &getList() const;
int sum = 0;
void ​dfs​(vector<NestedInteger>& nestedList, int degree) {
for (auto NI : nestedList) {
if (NI.isInteger()) sum += degree * NI.getInteger();
else dfs​(NI.getList(), degree + 1);
}
}
int depthSum(vector<NestedInteger>& nestedList) {
​dfs​(nestedList, 1);
return sum;
}

❌364 Nested List Weight Sum II ++


int depthSum​Inverse​(vector<NestedInteger>& nestedList) {
vector<int> ret;
​for ​(NestedInteger NI : nestedList) dfs​(NI, 0, ret);
int sum = 0;
​for ​(int i = ret.size() - 1, level = 1; i >= 0; i--, level ++)
sum += ret[i] * level;
return sum;
}
void dfs(NestedInteger NI, int depth, vector<int>& ret) {
​if ​(ret.size() < depth + 1) ret.push_back(0);
​if ​(NI.isInteger()) ret[depth] += NI.getInteger();
​else ​for ​(auto NI : NI.getList()) dfs​(NI, depth + 1, ret);
}

606. Construct String from Binary Tree


string tree2str(TreeNode* t) {
if (!t) { return "";}
if (!t->left && !t->right) {return to_string(t->val);}
if (!t->right) {return to_string(t->val) + "(" + tree2str(t->left) + ")";}
return to_string(t->val) + "(" + tree2str(t->left) + ")" + "(" + tree2str(t->right) +")";
}
❌46 Permutations I (no duplicates) ++
vector<vector<int>> permute(vector<int>& nums) {
vector<vector<int>> result;
dfs(nums, 0, result);
return result;
}
void dfs(vector<int>& nums, int begin, vector<vector<int>>& result) {
if (begin >= nums.size()){ ​//terminate dfs!
result.push_back(nums);
return;
}
for (int i = ​begin​; i < nums.size(); i++) {
​swap​(nums[i], nums[begin]);
dfs(nums, begin + 1, result); ​//ERROR: not dfs(nums, i, result)! it's begin+1!!! The
next position to swap.
​swap​(nums[i], nums[begin]);
}
}

❌47 Permutations II (with duplicates) ++


vector<vector<int>> permuteUnique(vector<int>& nums) {
vector<vector<int>> result;
​sort​(nums.begin(), nums.end());
recursion(nums, 0, result);
return result;
}
//* remove duplicates with unordered_set, works but needs extra space
void recursion(vector<int>& nums, int begin, vector<vector<int>>& result){
if (begin >= nums.size()){
result.push_back(nums);
return;
}
​unordered_set<int>​ set;
for (int i = ​begin​; i < nums.size(); i++) {
if (set.find(nums[i]) != set.end()) ​continue​;
set.insert(nums[i]);
swap(nums[begin], nums[i]);
recursion(nums, begin + 1, result);
swap(nums[begin], nums[i]);
}
return;
}
39 Combination Sum ++
​void combinationSum(vector<int>& candidates, int target, vector<vector<int>>& ret, vector<int>&
combination, int begin) {
if (​target==0​){
ret.push_back(combination);
return;
}
for (int i=begin; i<candidates.size() && target >= candidates[i]; i++){
combination.push_back(candidates[i]);
combinationSum(candidates, ​target-candidates[i],​ ret, combination, i);
combination.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
std::sort(candidates.begin(), candidates.end());
vector<vector<int>> ret;
vector<int> combination;
combinationSum(candidates, target, ret, combination, 0);
return ret;
}

40 Combination Sum II
​vector​<​vector​<​int​> > combinationSum2(​vector​<​int​> &num, ​int​ target)
{
​vector​<​vector​<​int​>> res;
​sort​(num.begin(),num.end());
​vector​<​int​> local;
findCombination(res, ​0,
​ target, local, num);
​return​ res;
}
​void​ ​findCombination​(​vector​<​vector​<​int​>>& res, ​const​ ​int​ order, ​const​ ​int​ target, ​vector​<​int​>&
local, ​const​ ​vector​<​int​>& num)
{
​if​(target==​0​)
{
res.push_back(local);
​return​;
}
​else
{
​for​(​int​ i = order;i<num.size();i++) ​// iterative component
{
​if​(num[i]>target) ​return​;
​if​(​i>order && num[i]==num[i-1]​) ​continue​; ​// check duplicate combination
local.​push_back​(num[i]),
findCombination(res,i+​1​,target-num[i],local,num); ​// recursive componenet
local.​pop_back​();
}
}
}

216 Combination Sum III


vector<vector<int>> combinationSum3(int k, int n) {
vector<vector<int>> ret;
vector<int> local;
combinationSum3(ret, local, k, n);
return ret;
}
void combinationSum3(vector<vector<int>>& ret, vector<int>& local, int k, int n) {
if (local.size() == k && n == 0) {
ret.push_back(local);
return;
}
if (local.size() == k) {
return;
}
if (n < 0) {
return;
}
for (int i = local.empty() ? 1 : local.back() ​+ 1​; i <= 9; i++) {
local.push_back(i); ​//allows repeated withou t​ ​+1
combinationSum3(ret, local, k, n - i);
local.pop_back();
}

❌282 Expression Add Operators

❌254 Factor Combinations


vector<vector<int>> getFactors(int n) {
vector<vector<int>> result;
vector<int> row;
dfs(result, row, n);
return result;
}
void dfs(vector<vector<int>>& result, vector<int>& row, int n) {
int i = row.empty() ? 2 : row.back();
for (; i <= n / i; i++) {
if (n % i == 0) {
row.push_back(i);
row.push_back(n / i);
result.push_back(row);
​row.pop_back();
​dfs(result, row, n / i);
​row.pop_back();
}
}
}

❌113 Path Sum II


vector<vector<int>> pathSum(TreeNode* root, int sum) {
vector<vector<int>> ret;
vector<int> path;
dfs(root, sum, path, ret);
return ret;
}
void dfs(TreeNode* root, int sum, vector<int>& path, vector<vector<int>>& ret) {
if (!root) {return;}
path.push_back(root->val);
if (!root->left && !root->right && ​sum == root->val​) {​ret.push_back(path);}
dfs(root->left, sum ​- root->val​, path, ret);
dfs(root->right, sum ​- root->val​, path, ret);
path.pop_back();
}

Tree, Graph
98. Validate Binary Search Tree
bool isValidBST(TreeNode* root) { return isValidBST(root, ​NULL​, ​NULL​);}
bool isValidBST(TreeNode* root, ​TreeNode*​ ​min​, ​TreeNode*​ ​max​){
if (!root) return true;
if (min && root->val <= min->val) return false;
if (max && root->val >= max->val) return false;
return isValidBST(root->left, ​min​, ​root​) && isValidBST(root->right, ​root​, ​max​);
}
102 Binary Tree Level Order Traversal

✅❌ 103 Binary Tree Zigzag Level Order Traversal


vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
vector<vector<int>> ret;
if (!root) {return ret;}
queue<TreeNode*> m_queue;
m_queue.push(root);
bool rev = false;
while (!m_queue.empty()) {
int sz = m_queue.size();
vector<int> temp;
for (int i = 0; i < sz; i++) {
TreeNode* tempNode = m_queue.front();
m_queue.pop();
temp.push_back(tempNode->val);
if (tempNode->left) {m_queue.push(tempNode->left);}
if (tempNode->right) {m_queue.push(tempNode->right); }
}
if (rev) { reverse(temp.begin(), temp.end());}
ret.push_back(temp);
rev = !rev;
}
return ret;
}

❌156 Binary Tree Upside Down ++

​Sol1. Iterative
TreeNode* upsideDownBinaryTree(TreeNode* root) {
TreeNode* parent = nullptr; //cur’s parent node
TreeNode* next = nullptr; //cur’s left node
TreeNode* right = nullptr; //cur’s sibling right
TreeNode* cur = root;
while (cur) {
next = cur->left;
cur->left = right;
right = cur->right;
cur->right = parent;
parent = cur;
cur = next;
}
return parent;
}
❌❌❌​Sol2. Recursive
TreeNode* upsideDownBinaryTree(TreeNode* root) {
if (!root || !root->left) { return root;}
TreeNode* cur_left = root->left;
TreeNode* cur_right = root->right;
TreeNode* new_root = upsideDownBinaryTree(root->left);
cur_left->left = cur_right;
cur_left->right = root;
root->left = nullptr;
root->right = nullptr;
return new_root;
}

Hashmap, Priority Queue


❌347 Top K Frequent Elements ++++
struct compNode{
bool operator () (pair<int, int> p, pair<int, int> q) const {
return p.second > q.second;
}
};
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, int> m_map;
for (int num : nums) m_map[num] ++;
priority_queue<pair<int, int>, vector<pair<int, int>>, compNode> pq;
for (auto it = m_map.begin(); it != m_map.end(); it++) {
if (pq.size() < k) {
pair<int, int> temp = make_pair(it->first, it->second);
pq.push(temp);
continue;
}
if (it->second > pq.top().second) {
pq.pop();
pair<int, int> temp = make_pair(it->first, it->second);
pq.push(temp);
}
}
vector<int> ret;
while (!pq.empty()) {
ret.push_back(pq.top().first);
pq.pop();
}
return ret;
}
说了map和hash的做法,负责度也都分析了,最好的n+nlogk,还说不行,问有没有linear,答曰用partition吧,
不过根本没有复习过这个code具体实现,就是根据脑子里的印象写了个大概,然后时间到。这轮感觉多少有被
黑的可能。问问题时就感觉在刁难,哪tm上来就最优解啊。

❌170 Two Sum III - Data structure design


class TwoSum {
unordered_map<int, int> m_map;
void add(int number) {m_map[number]++;}
bool find(int value) {
for (auto nc : m_map)
if (m_map.count(value - nc.first) && (nc.first != value - nc.first || nc.second > 1))
return true;
return false;
}
};

❌149 Max Points on a Line ++++


用double/string来当slope? Doesn’t work!
int maxPoints(vector<Point>& points) {
if (points.size() <= 1) {return points.size();}
int ret = 0;
for (int i = 0; i < points.size() - 1; i++) {
map<pair<int, int>, int> m_map;
int duplicate = 1, locaMax = 0;
for (int j = i + 1; j < points.size(); j++) {
if (points[j].x == points[i].x && points[j].y == points[i].y) {
duplicate ++;
continue;
}
int dy = points[i].y - points[j].y;
int dx = points[i].x - points[j].x;
int gcd = GCD(dy, dx);
m_map[{dy / gcd, dx / gcd}] ++;
locaMax = max(locaMax, m_map[​{dy / gcd, dx / gcd}​]);
}
ret = max(ret, locaMax + duplicate);
}
return ret;
}
int GCD(int a, int b) {return b == 0 ? a : GCD(b, a % b);}
Array
❌ 277 Find the Celebrity
// Forward declaration of the knows API.
bool knows(int a, int b);
int findCelebrity(int n) {
if (n <= 1) {return n;}
int candidate = 0;
for (int i = 0; i < n; i++){
if (!knows(i, candidate)) candidate = i;
}
for (int i = 0; i < n; i++){
if (i == candidate) ​continue​;
if (!knows(i, candidate)) return -1;
if (knows(candidate, i)) return -1;
}
return candidate;
}
};

Variant:
类似于find celebrity. 叫​做find influencer​. input是一个2d boolean array, 每个index 代表一个人。比如
matrix[1][0] = true,表示1 follow 0,如果是matrix[1][0] = false,表示1没有follow 0. influencer的定义是所有除了他
以外的人都follow他,而他没有follow任何人。先说了一个暴力法O(n^2),他说能O(n)解吗,写了一个用queue的
方法,他又问能不用额外空间吗。然后经他提示,写了个不用额外空间的O(n)解法。

✅243 Shortest Word Distance


int shortestDistance(vector<string>& words, string word1, string word2) {
int ret = INT_MAX;
int lastWord1 = -1, lastWord2 = -1;
for (int i = 0; i < words.size(); i++) {
if (words[i] == word1) {
lastWord1 = i;
if (lastWord2 != -1) {ret = min(ret, lastWord1 - lastWord2);}
}
else if (words[i] == word2){
lastWord2 = i;
if (lastWord1 != -1) {ret = min(ret, lastWord2 - lastWord1);}
}
}
return ret;
}
❌✅244 Shortest Word Distance II
unordered_map<string, vector<int>> m_map;
WordDistance(vector<string> words) { ​//constructor, set up the storage
for (int i = 0; i < words.size(); i++) {m_map[words[i]].push_back(i);}
}
int shortest(string word1, string word2) {
int ret = INT_MAX;
int i = 0, j = 0;
while (i < m_map[word1].size() && j < m_map[word2].size()) {
ret = min(ret, abs(m_map[word1][i] - m_map[word2][j]));
if (m_map[word1][i] > m_map[word2][j]) { j ++;}
else { i ++;}
}
return ret;
}

53 Maximum Subarray
int maxSubArray(vector<int>& nums) {
if (nums.size() == 0) { return 0;}
vector<int> cumsum(nums.size() + 1);
cumsum[0] = 0;
for (int i = 1; i <= nums.size(); i++) {
cumsum[i] = cumsum[i - 1] + nums[i - 1];
}
int cur_min = 0; //easy to make mistake here!!!
int cur_max = INT_MIN;
for (int i = 1; i < cumsum.size(); i++) { //start from 1! cur_max =
max(cur_max, cumsum[i] - cur_min);
cur_min = min(cur_min, cumsum[i]);
}
return cur_max;
}

❌152 Maximum Product Subarray


int maxProduct(vector<int>& nums) {
int ret = nums[0];
for (int i = 1, imax = nums[0], imin = nums[0]; i < nums.size(); i++) {
if (nums[i] < 0) {
swap(imax, imin);
}
imax = ​max​(nums[i], imax * nums[i]);
imin = ​min​(nums[i], imin * nums[i]);
ret = max(ret, imax);
}
return ret;
}

❌​235 Lowest Common Ancestor of a Binary Search Tree +


TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
while ((root->val - p->val) * (root->val - q->val) > 0 ) {
root = root->val > p->val ? root->left : root->right;
}
return root;
}

❌​236. Lowest Common Ancestor of a Binary Tree +


TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (!root || root == p || root == q) { return root;}
TreeNode* left = lowestCommonAncestor(root->left, p, q);
TreeNode* right = lowestCommonAncestor(root->right, p, q);
if (left && right) {return root;}
if (left) {return left;}
if (right) {return right;}
return NULL;
}

Variant: has parent node!


用 HashSet 存所有one的ancestor, 然后遍历two的ancestor,找第一个在set里的

Thread-safe Hashtable put get 实现 (multithreading)


初级版: (难点是c++里面的lock syntax, 面试的那哥们就是挂在这儿的)
https://xinxiwang.wordpress.com/2014/01/18/thread-safe-map-for-c/
Follow up: implement without lock
方案一: 把lock用c++implement实现,比如test and set 之类的atomic instru
方案二:减少多个thread access same data的可能性
这位大哥给了一个Performance优化的解法
https://www.linkedin.com/pulse/simple-way-implement-concurrent-mapset-c-huan-xia/
OK, the typical operation on map/set are: inserting, removing, finding.

Let’s look at finding first. If the content of a map/set is fixed, finding is thread-safe by nature. (for most implementations,
we do not discuss the rare cases)

How about inserting and removing? To make it concurrency, it must be able to perform more than one operations at the
same time by different threads. This easily come up with an idea of partition an array. By partitioning an array into different
section, each section can be accessed separately by different threads.

Is it possible to partition a map/set to avoid locking a whole map/set?


If we just focus on a single map/set, this might not be obvious. However, it can be done using multiple maps/sets, like this:

For given key and value types:

map<key1, map<key, value>>

where key1 is the hash value of key.

But when an inserting or removing is invoked, the inner map is locked only instead of lock the whole outer map.

As long as the content of outer map is fixed, it does not need to be locked/unlocked.

If the number of hash slots is big enough, in normal cases, the chance of accessing a same inner map by more than one
threads can be reduced significantly.

This makes a concurrent map.

Look at the GitHub repository here for a sample implementation based on the ideas above:
https://github.com/huxia1124/ParallelContainers
看 ParallelContainers/STXUtility.h

N dimensional image volume


interface里有两个函数,一个可以取得各维度的size,一个可以可以取得指定pixel的值。编写程序求整
个volume的和。这题可以用recursive 和 non-recursive 两种方法答. 这个volume不能整块的access,
只能一次用一个接口函数取得某一个pixel的值。接口函数可以是 Integer get(List<Integer>)。传入这个
pixel的位置。另外一个接口函数可以取得各个维度的size,返回一个List。Volume 可以是任意维数 N
。 N可以是任何自然数。

求两个linked list 是否 merge。+++


要求考虑有环 和 没环的情况. 有merge的意思是不是说两个分别属于两个list的node同时指向同一个下
一个node. 其实这题是把很多linked list的小题合起来了。我当时是先判断每个linked list 是否有环,之
后再分成三种情况讨论。1. 两个都没有环。2. 其中一个有环,一个没有环(这种情况一定不相交,可
以自己画一画就能明白)。 3. 两个都有环。 两个都有环就要判断是否 share 一个环.
写的时候还要注意modulize。是否要求空间O(1), 是的话,检测第一个有环则断开, 检测第二个这时如
果有环就不merge(share 的环已经被断开), 没环的环就用没环的方法检测是否merge

多维数组求和
Variant
follow up是找出这些份 返回一个List<List<Integer>>

76 Minimum Window Substring +++


No duplicates and has duplicates

❌ 721. Accounts Merge


如果两个用户id有同样的邮箱说明是同一个人,input有共同邮箱的人们和n个id,输出有多少人,bfs或者
unionfind。

Search range??

flatten 4-direction doubly linked list


就是有上下左右四个方向的子node,每个子node也可以有上下左右四个方向的子node,要求把这玩意儿转换成
正常的doubly linkedlist,O(1) space,所以不能recursive,因为有stack space。
当时就懵逼了,讨论了很久才搞清楚思路,基本没什么时间写code,于是挂了(当然是主观判断,也可能是吃
饭时候菜叶塞牙缝了嘛哈哈,开个玩笑...)

思路是这样:
1. 给定任意一个node,往left走到head,往右一直走到tail(这个操作要重复很多遍所以可以定义getHead
getTail两个function);.
2. 从head开始走,判断有没有up node,有的话,从up node一直往左走到新的head,一直往右走到新的tail,把
这个head链接到原来的tail,把旧的tail的值赋成新值
3. 把up node和刚才那个node之间的up & down link断掉,有小trick,不细讲了;
4. 判断有没有down node,有的话,重复上面两步操作;
5. 操作结束或者本来就没有up down node的话就往下,一直走到那个被更新过很多遍的tail...

当然不一定全都挪到tail,也可以挪到node.next,但个人觉得挪到tail比较好visualize。
❌​followup如果有环怎么办。要求都是constant space???
这个是O(1) space, 基本上是O(N) time, 虽然getHead和getTail两个function可能跑很多遍,最终应该也还是O(N)
吧?不过最后还讨论到这一步。
public class MultiListToDoubleList {
static class MultiListNode {
int val;
MultiListNode pre;
MultiListNode next;.
MultiListNode up;.
MultiListNode down;.
}
public static void convert(MultiListNode head) {
if (head == null) { return;}
MultiListNode tail = head;
while (tail.next != null) {​tail​ = tail.next;}
MultiListNode ​cur ​= head;
while (cur != null) {
if (cur.up != null) {
MultiListNode up_head = cur.up;
​while (​up_head​.pre != null) {​up_head ​ = ​up_head​.prev;}
tail.next = up_head;
up_head.pre = tail;
​while (tail.next != null) {tail = tail.next;} ​//update tail!!!
​cur.up.down = null;
cur.up = null;
}
if (cur.down != null) {
MultiListNode dn_head = cur.down;
​while (​dn_head​.pre != null) {​dn_head ​ = ​dn_head​.prev;}
tail.next = dn_head;
dn_head.pre = tail;
while (tail.next != null) {tail = tail.next;}
cur.down.up = null;
cur.down = null;
}
cur = cur.next;.
}
}.
}

3 degree好友

设计一个支持produce h和o consume并生成h2o的class

找convex function的min

205. Isomorphic Strings


bool isIsomorphic(string s, string t) {
int Ms[256] = {0}, Mt[256] = {0};
for (int i = 0; i < s.size(); i ++) {
if (Ms[s[i]] != Mt[t[i]]) {
return false;
}
Ms[s[i]] = i + 1;
Mt[t[i]] = i + 1;
}
return true;
}

349 Intersection of Two Arrays

实现 string replace

✅344 Reverse String


string reverseString(string s) {
int sz = s.length();
for (int i = 0; i < sz / 2; i++) {
swap(s[i], s[sz - i - 1]);
}
return s;
}

❌​Variant
Should be within a sentence. Do not change the position of each word, but reverse them!

❌56 Merge Intervals ++


vector<Interval> merge(vector<Interval>& intervals) {
vector<Interval> ret;
if (intervals.empty()) {
return ret;
}
sort(intervals.begin(), intervals.end(), [](Interval a, Interval b){return a.start <
b.start;});
ret.push_back(intervals[0]);
for (int i = 1; i < intervals.size(); i++){
if (ret.back().end < intervals[i].start) {
​ret.push_back​(intervals[i]);
}
else {
​ ret.back().end​ = max(ret.back().end, intervals[i].end);
}
}
return ret;
}
有 add 和getcoverlength 两个method。要求不是以前的那种根据call frequency写而是假定两个method的频率是
随机的。要求达到时间复杂度最佳。。最先用了直接add 到list 然后call get 的时候sort 的方法。然后讨论了很久
最后说用treeSet 在add 里面,这样总时间复杂度更小

(1) LinkedList 插入使得每次插入后start保持有序并保持所有的节点都是disjointed 同时计算totalbusy。 O(N)的


add时间和O(1)get时间
(2) Binary search tree. 也就是map,treemap这种。 保持插入后有序,O(logN) add O(N) get时间
follow up 如果需要remove interval 用哪种方式?

57 Insert Interval
vector<Interval> insert(vector<Interval>& intervals, Interval newInterval) {
vector<Interval> ret;
int idx = 0;​//1. Deal with intervels before new
while (idx < intervals.size() && newInterval.start > intervals[idx].end) {
ret.push_back(intervals[idx]);
idx++;
} ​//2. Merge with intervls overlapping with new
while (idx < intervals.size() && newInterval.end >= intervals[idx].start) {
newInterval.start = min(newInterval.start, intervals[idx].start);
newInterval.end = max(newInterval.end, intervals[idx].end);
idx++;
} ​//3. Deal with intervals after
ret.push_back(newInterval);
while (idx < intervals.size()) {
ret.push_back(intervals[idx]);
idx++;
}
return ret;
}

❌127 Word Ladder

DFS暴力解了。follow up是给一个dependency tree,要输出build次序,从叶到根。我说可以 BFS,复杂度是


n*log(n) 。面试官问,could we do better. 我说,那就把它convert成DAG (O(n)),拓扑排序可以O(n),这样
最后是O(n).
给你一个int c, 返回boolean 表示是否可以有a^2 + b^2 = c^2 存在,a,b,c > 0

Math
13. Roman to Integer ++++
int romanToInt(string s) {
int len = s.length();
if (len == 0) {return 0;}
unordered_map <char, int> T ={
{'I', 1},
{'V', 5},
{'X', 10},
{'L', 50},
{'C', 100},
{'D', 500},
{'M', 1000},
};
int ret = T[s[len - 1]];
for (int i = len - 2; i >=0; i--) {
if (T[s[i]] >= T[s[i + 1]]) {ret ​+=​ T[s[i]];}
else{ret ​-=​ T[s[i]];}
}
re​turn ret;
}
❌​Variant:
再写个验证罗马数字是否valid function

✅12. Integer to roman


string intToRoman(int num) {
string ret = "";
unordered_map<int, pair<char, char>> m_map;
m_map[1] = {'I', 'V'};
m_map[10] = {'X', 'L'};
m_map[100] = {'C', 'D'};
m_map[1000] = {'M', 'M'};
int power = 1000;
while (power) {
int digit = num / power;
if (digit == 5) {ret = ret + m_map[power].second;}
else if (digit == 4) {ret = ret + m_map[power].first + m_map[power].second;}
else if (digit < 4) {while (digit--) {ret = ret + m_map[power].first;}}
else if (digit == 9) {ret = ret + m_map[power].first + m_map[power * 10].first;}
else {
ret = ret + m_map[power].second;
while (digit-- > 5) {ret = ret + m_map[power].first;}
}
num %= power;
power /= 10;
}
return ret;
}

✅ 238. Product of Array Except Self

187 Repeated DNA Sequences

Sol 1. Naive, a lot of storage


vector<string> findRepeatedDnaSequences(string s) {
vector<string> ret;
unordered_map<string, int> m_map;
int sz = s.length();
for (int i = 0; i <= sz - 10; i++) {
string temp = s.substr(i, 10);
if(++m_map[temp] == 2) {
ret.push_back(temp);
}
}
return ret;
}

Sol 2. Compress! Last three bit of ACGT


先算数据很大怎么存,算到底占多大空间,如何优化,然后才让写
给一个数字组成的sequence和一个target, 可以在数字之间加 + - * / 四种运算法,返回可以算出计算结果是target
的string
vector<string> findRepeatedDnaSequences(string s) {
vector<string> ret;
unordered_map<int, ​bool​> m_map;
int sz = s.length();
int t, i;
for (t = 0, i = 0; i < 9; i++) ​{ t = t << 3 & 0x3FFFFFFF | s[i] & 7;}
for (; i < sz; i++) {
t = t << 3 & 0x3FFFFFFF | s[i] & 7;
if (m_map.find(t) == m_map.end()) { m_map[t] = ​true​; }
else {
if (m_map[t]) {
m_map[t] = ​false​;
ret.push_back(s.substr(i - 9, 10));
}
}
}
return ret;
}

地图
上面有很多点, 每个点是个object, x, y 坐标都给了, 比如{x: 5, y: 5}
已知 包含所有点的 array, 某一个点,和半径d, 写一个function 返回到这个点的距离小于或等于d 的所有点。
怎么优化。我当时答得是把整个地图分成小的区域,每一小块2d的正方形。然后找这个点所在的方块和周围的几
个方块。这样就不用遍历地图里所有的点了。

按权重返回随机数。
比如{4: 3, 2: 2, 1: 1},就是指4的权为3,2的权为2,1的权为1,那么返回4的概率是3/7

打印经过城市停车站的所有路线。
比如城市0有一个车站X,城市1有A, B两个停车站,2有C, D, E,3有Y。那么从X到Y的所有路线有:
XY 经过1和2时不停车
XAY, XBY 在1停次车
XCY, XDY, XEY 在2停次车
XACY, XADY, XAEY, XBCY, XBDY, XBEY 在1, 2都停次车。
我一开始用在一个城市停的结果加上在两个城市停的结果做,面试官就问我这是一个排列还是组合。我没明白他
的意思,直到他点明其实这是个排列,就是在每个城市选择每个停车站各一次+不停

一个function实现计算器里的undo以及redo功能。
其实就是考数据结构里的stack。最后的拓展题感觉在问system design,问我如果这种undo以及redo操作是用在
占据很大存储空间以及用户量很大的data上该怎么办,我说那就给每个数据加上index,undo以及redo只用在
index上,最后再用index去取数据。。。
Someone’s Summary?

1. Two Sum8. String to Integer (atoi)12. Integer to Roman13. Roman to Integer20. Valid Parentheses21.
Merge Two Sorted Lists23. Merge k Sorted Lists31. Next Permutation33. Search in Rotated Sorted Array34.
Search for a Range39. Combination Sum40. Combination Sum II46. Permutations47. Permutations II50.
Pow(x, n)53. Maximum Subarray56. Merge Intervals57. Insert Interval60. Permutation Sequence62. Unique
Paths63. Unique Paths II65. Valid Number68. Text Justification70. Climbing Stairs72. Edit Distance74. Search
a 2D Matrix75. Sort Colors76. Minimum Window Substring98. Validate Binary Search Tree100. Same
Tree101. Symmetric Tree102. Binary Tree Level Order Traversal103. Binary Tree Zigzag Level Order
Traversal104. Maximum Depth of Binary Tree109. Convert Sorted List to Binary Search Tree126. Word Ladder
II127. Word Ladder135. Candy136. Single Number137. Single Number II139. Word Break140. Word Break
II149. Max Points on a Line150. Evaluate Reverse Polish Notation151. Reverse Words in a String152.
Maximum Product Subarray155. Min Stack156. Binary Tree Upside Down160. Intersection of Two Linked
Lists169. Majority Element170. Two Sum III - Data structure design173. Binary Search Tree Iterator186.
Reverse Words in a String II187. Repeated DNA Sequences189. Rotate Array198. House Robber200. Number
of Islands205. Isomorphic Strings210. Course Schedule II213. House Robber II215. Kth Largest Element in an
Array216. Combination Sum III226. Invert Binary Tree232. Implement Queue using Stacks236. Lowest
Common Ancestor of a Binary Tree238. Product of Array Except Self240. Search a 2D Matrix II243. Shortest
Word Distance244. Shortest Word Distance II245. Shortest Word Distance III254. Factor Combinations256.
Paint House260. Single Number III261. Graph Valid Tree265. Paint House II277. Find the Celebrity295. Find
Median from Data Stream297. Serialize and Deserialize Binary Tree305. Number of Islands II311. Sparse
Matrix Multiplication319. Bulb Switcher337. House Robber III339. Nested List Weight Sum341. Flatten Nested
List Iterator347. Top K Frequent Elements349. Intersection of Two Arrays350. Intersection of Two Arrays II364.
Nested List Weight Sum II366. Find Leaves of Binary Tree367. Valid Perfect Square377. Combination Sum
IV380. Insert Delete GetRandom O(1)381. Insert Delete GetRandom O(1) - Duplicates allowed409. Longest
Palindrome438. Find All Anagrams in a String464. Can I Win.
Not leetcode ones:1. Tournament tree2. Triangle count3.BST insert/delete/find4.Convex hull5.single valid
tree6.四向鍊錶打平7. Max stack all O(1), Mid stack8.N nearest points9. Max palindrome sequence

Leetcode contest

Bold Words in String

class Solution {
public:
string boldWords(vector<string>& words, string S) {
string ret;
vector<pair<int, int>> pos;
for (string word : words) { //for each word, find all appearances in S
size_t firstpos = S.find(word, 0);
while (firstpos != string::npos) {
pos.push_back({(int)firstpos, -1});
pos.push_back({(int)firstpos + word.size(), 1});
//cout << word << " " << firstpos<< endl;
firstpos = S.find(word, firstpos + 1);
}
}

sort(pos.begin(), pos.end());
int accu = 0;
vector<pair<int, int>> final_pair;
//bool pre_zero = true;
int bold_begin = -1;
for (int i = 0; i < pos.size(); i++){
if (accu == 0) {
bold_begin = pos[i].first;
}
accu += pos[i].second;

if (accu == 0) {
final_pair.push_back({bold_begin,pos[i].first});
//pre_zero
//cout << bold_begin << " " << pos[i].first << endl;
}
}

if (final_pair.empty()) {
return ret;
}

ret = "";
int last = 0;
for (auto boldpair : final_pair) {
cout << ret << " ";
ret = ret + S.substr(last, boldpair.first - last);
//cout << S.substr(last, boldpair.first - last) << " ";
ret = ret + "<b>" + S.substr(boldpair.first, boldpair.second - boldpair.first) + "</b>";
//cout << S.substr(boldpair.first, boldpair.second - boldpair.first) << endl;
last = boldpair.second;
}
ret = ret + S.substr(last);
return ret;
}
};

Host Leader (1 hour):

● Talent​: ability to do the work and potential to learn. It's important to understand the process the
candidate uses to go from beginning to end.
● Thinking​ ​& problem solving​: figuring out the problem, developing solutions and alternatives, decision
making
● Team description and fit​: working with others, coaching, collaborating, influencing, training, being
coached
● Organizational fit​: pace, level of sophistication, flexibility, etc.
● Motivation​: general work-ethic and self-motivation to apply effort to do the work required.
*Tip:​ Discuss tradeoffs of different systems and migrations that you’ve worked on, and how those were
executed.
*Be ready to discuss your most significant accomplishment, why was it a huge success to you, others on your
team and even the company?
🔴
Simpoint accuracy applying better algorithm.
Geekbench checkpoints.
Emulation platform.

Coding Interviews: T ​ wo of the below interviews will focus on coding questions. Just like in the phone
interview, these will focus on CS fundamentals, data structures, and math (algorithms, graph theory, etc.). You
won’t be given all the information you need to solve the problem. Instead, you’ll need to ask clarifying
questions to identify use cases, edge/corner cases, etc. This is to get a sense of how you approach a problem.
It’s going to be a very interactive interview, so ask a lot of questions and only start implementing your solution
when you feel you have a good understanding of the problem. If you start struggling with your solution, explain
what you did and why so the interviewers are able to give you hints to get you moving along.
- During these interviews, the engineers will be looking for ​1)​ were you able to come up with a working
solution; ​2)​ how complete your code is; ​3) ​cleanliness of code; ​4)​ time to completion; ​5)​ how optimal your
solution was (if they ask you if you can optimize your solution, look at your algorithm).

Coding and Algorithms 1 (1 hour):


● Coding 1 covers problems that involve ​extensive ​whiteboard coding with only moderate
algorithmic complexity. The focus of this interview should be on the modularity and extensibility of the
code that your write, as well as on finding and fixing bugs and other errors.
● Many of these sessions involve ​pointers, edge cases, abstraction​, or all of the above, and are
intended to imitate the kind of day-to-day coding that happens once the design and implementation
strategy for a project has been settled on.

Coding and Algorithms 2 (1hour):


● Coding 2 will focus more on advanced analytical ability, algorithmic skill, and problem solving ability.
The focus (in contrast to coding 1) is much less around the actual code that comes out in this module
the ​overall runtime and scalability​ of the solutions will matter much more.

Technical Taste & Communications (1 hour):

One of the interviews will focus on technical communication. This will be a deep dive into projects you worked
on, technologies used, and architectural decisions.
Make sure you're able to speak of an ​interesting/challenging project​ you worked on and be able to explain
the ​challenges faced, lessons learned, and technical details​. They’ll be looking for excitement or interest in
the projects you worked on because they want to work alongside engineers who are passionate about what
they do.
● Start at a ​high level​ explaining the project (why was it needed, what was it used for, who would use it,
etc.), then explain what your team did, then what you were responsible for. Make sure you have a good
understanding of the decisions that were made and a holistic understanding of the work.
● Think about how you would go about helping on-board a new employee to your existing team and
environment and how you would go about helping them understand the​ ins and outs of your group
and how it integrates with your engineering organization, how do you work with product, and how does
it all fit together?
● Think about how you might do a quick white board illustration around this to help them better
understand as well.

Software Design & Architecture (1 hour):

● Architecture will cover problems in end to end design of complex, internet-scale systems with many
requirements, typically requiring tradeoff decisions.
● The focus of this interview will be your ability to ​understand ​the problem, consider appropriate
design alternatives, make appropriate ​tradeoffs​, and choose an approach that solves that stated
problem. Ideally, the solution will be ​extensible t​ o support likely future requirements and will be
practical to implement and test. They will also be looking for you to demonstrate knowledge of
"standard" technologies, including open source components.
*Watch this video & read this link!
http://www.infoq.com/presentations/linkedin-architecture-stack​ &
https://www.linkedin.com/pulse/technical-design-interview-guide-success-joey-addona

Lunch (1 hour):

● This is your opportunity to ​ask ​well thought out questions about Linkedin and what you know about
Linkedin and what you’d like to know more about
Promote? Team matching? Culture? How the infinity vacation works? Future development??

● Expect to have a leisurely conversation about the newest open-source technologies out there
● Think about what it is that you’re currently passionate about with your current job or what you have
been passionate about in the past with your current company and be clear as to why you feel
Linkedin is a company you’d like to work for

*Lastly, a few more practice problems and soft skills that are being looked for:

Soft Skills:
● Reiterate the questions asked to ensure that what you ​heard and understood​ is what the interviewer
meant.
● Talk to the interviewer (I know they’re an engineer) through your thought process while you’re coding
and/or architecting solutions to the questions asked.
● Spend a short period of time to ​clarify t​ he requirements before assuming anything.
● Ensure your code on the whiteboard is NOT messy as they will be critical of these types of things
● Read up on some projects Linkedin is working on so that you can have some good questions ready

Das könnte Ihnen auch gefallen