Google Interview Summary 4


https://docs.google.com/document/d/1qxA2wps0IhVRWULulQ55W4SGPMu2AE5MkBB37h8Dr58/

频率 3次。

1。LC676 magic dictionary                各种变种 所求word再dict单词差一个字母
思路:两种解决思路。可以把words按length存起来然后每有词想search时候遍历查找相符。第二种是存的时候就开始删,记得要记录删的地方的index,最后和所求删的index是否相等
2。LC849 选座位 跟exam room
思路:注意边界条件和怎么判断距离
http://massivealgorithms.blogspot.com/2018/11/leetcode-849-maximize-distance-to.html

3。LC418 sentence screen fitting
思路:见lc
http://massivealgorithms.blogspot.com/2016/10/leetcode-418-sentence-screen-fitting.html
5。LC844 Backspace string compare
思路:简单stack秒杀 注意follow up是O(1) space → two pointers
6。 LC394 s = "3[a]2[bc]", return "aaabcbc".
思路:recursion call括号中间的项
7。LC334 给一个array,arr[i] < arr[j] < arr[k] given 0 ≤ i < j < k ≤ n-1 else return false.
思路:从左到右过array,用两个变量存第一小和第二小的数(初始最大值),更新尽量小的数,若同时遇到第三小的数,则为true
8。LC774 加油站最短距离
思路:用binary search寻找最短的距离,边search边找当前mid是否符合mid条件,注意判断边界条件和mid==target怎么走

这个帖子里要求必须用dp,这里贴一个dp解法。
Dp[i][j]表示前i个加油站增加j个站点最小的最大距离.


9。LC337 二叉树House Robber
思路:dfs+dp存抢当前node和不抢当前node的最大值
10。LC340 longest substring with at most K distinct characters
思路:基本滑动窗口问题,遇到就是赚到

12。LC426 BST撸直变成双向链表 首尾相接
思路:简单DFS。想清楚思路!!!开始dummy当prev留住head,最后prev是tail。其中prev可当做class变量
13。LC215 Kth largest element in an array
思路:可以先用优先队列装个怂,再用quick select
思路:二维dp问题。dp[left][right]代表能在当前段内能扎出来的最高分。memorize是当dp非零则是没计算过。
15。LC769 LC768 问一个array在怎样trunk sorted之后只经过拼接就能得到升序array
思路:[0~n]的array做法为maintain一个max变量存当前max,当max==当前index则count++
无限制array时候做法为构造两个新的array存maxOfLeft和minOfRight。当一个数左看都比自己小,右看都比自己大的时候,则可以trunk。(这个更加generalize
http://massivealgorithms.blogspot.com/2019/02/leetcode-769-max-chunks-to-make-sorted.html
http://massivealgorithms.blogspot.com/2019/02/leetcode-768-max-chunks-to-make-sorted.html

16。LC505 the maze II 求total steps
思路:用BestFS+PQ+memorization做,注意撞墙别忘了往回退一步
17。LC96 Unique Binary Search Trees
思路:递归+memorization
18。LC834 Sum Of distances in tree
思路:两次遍历,更新count和res。第一次post order 第二次pre order
http://massivealgorithms.blogspot.com/2019/03/leetcode-834-sum-of-distances-in-tree.html
***
LC939 && LC963 给一堆坐标点,求坐标点形成的横平竖直矩形最小面积
思路:任取两点当对角线做矩形,存在set里。若已有set存在则因为另外一个对角线存在,更新面积
LC230: Kth smallest in BST,followup 若要改树怎么整 [改树是什么意思?有很多树call这个函数多次?]如果中间有人要insert node to BST的话,如何实现同样功能
思路:建一个TreeNodeWithCount,这样以后改的时候也是log n复杂度。改树的同时改TreeNodeWithCount
http://massivealgorithms.blogspot.com/2016/11/leetcode-230-find-k-th-smallest-element.html

4. 面试官迟到 15 分钟。面试时间实际为 30 分钟。给定一个 picture (二维)。里面有一些有色的像素,保证所有像素是相连的(上下左右相连),且只有一个联通块。返回一个最小矩阵,这个矩阵能包含所有的有色 pixel
这题是找上下左右的极大和极小值吗
是的 LC302原题,用二分查找做的,上下左右分别二分找边界
http://massivealgorithms.blogspot.com/2015/11/leetcode-302-smallest-rectangle.html

5. 给定一个棋盘,里面有一些棋子。你能移走这个棋子,当且仅当这个棋子的同行同列有其它棋子。要求最多能移走多少棋子。类似LC 947
思路:可以把所有棋子放到list里,每row,col存在的棋子再分别放到set of set of nodes里。用dfs思路第一轮删除任意一点,然后往后推第二次在上一次基础上清除任意满足要求的那个点,直到最后无点可清除时回溯看总共清除了多少。可mem
更新思路:用union find看能有多少组划分出来(如果同行或同列分成一组),然后最多能移走的棋子数=总棋子-组数(number of islands)
follow up :是应该用什么顺序拿,才能保证能拿最多 (这个follow up应该怎么解呢)尽量先把一个component里的都去掉?
优先拿掉不导致component数量增加的棋子。



recurrence relation: A[n][k] = min ( { max(A[k-1], sum(S[i+1], S[i+2], ..., S[n]))  for i = k-1, k, ..., n-1} ) 其中S表示task resource的数组,A[n][k]表示n个tasks, k days的每天最小resource值。
这题其实就是(lc410)
http://massivealgorithms.blogspot.com/2016/10/leetcode-410-split-array-largest-sum.html
国人。 一个只有正整数的list, 其中插入+, * 或者(),求得到式子最大的值。 e.g. [1,2,1,2 ]->  (1+2)*(1+2)=9. dp解, follow up, 如果有负数该怎么办, 如果想要拿到最大的式子该怎么办。
思路:类似burst balloon dp[i][j] = max of for (k : i ~ j  max(dp[i][k - 1] * dp[k][j], dp[i][k - 1] + dp[k][j]))

LC739 array of temperatures, tell me how many days have to wait till next warmer weather
思路:用stack从后往前存,每次看天气时候pop出比栈顶温度低的日子,再peek出比当前暖和的一天index

LC731 持续加intervals,问会不会出现triple booked
思路:按start end加到treemap里,start+1, end - 1,每次从小到大遍历treemap看是否存在count>2
https://massivealgorithms.blogspot.com/2018/04/leetcode-731-my-calendar-ii.html

LC736 非常难 parse lisp expression 注意边界条件和判断条件
思路:分情况 let mult add讨论,用一个parse function处理运算符以后的事宜
https://massivealgorithms.blogspot.com/2019/03/leetcode-736-parse-lisp-expression.html

LC768 乱序数组 chunk出最多组使得每组sort后整个sort好
思路:从右往左扫一遍最小值,从左到右扫一遍最大值。在第二遍途中若看到左最大<=右最小时++

Google Snapshot
实现三个functions, get, set, take snapshots。其实就是一个长度为N的Array。Set可以设置Index i的值,每次take snapshot, version + 1,并且记录下当前version下 Array里面的值。然后get方法可以得到某一个Version下,每一个Index的Array的值。就是非常Naive的方法,在Chromebook上写完了。写完之后有一个变量名Typo被指出。口头跑了Test case。Follow up 时空复杂度,并且要节省空间。
举例
初始 100001
take a snapshot 返回sid 1
改变成 100201.
take a snapshot 返回sid 2
这时lookup get(3,1)( get(index, snapshotID))应该返回0而不是2,这是version control的原理可是关键在怎么存最省空间

可以参考视频压缩,每隔若干帧保存一份完整的图像,期间只保存delta。重建图像的时候,从最近的full snapshot开始,然后apply 每个version的delta

  1. There are two colors in the matrix, find the shortest manhattan distance of two colors
  2. There are an array of lights. I have a list of intervals, eg [0,2) which means switch the light #0, and light #1. I want to know the final state of these lights

朋友的面经,请问这两道有什么好的方法?
第一题用BFS,第二题区间开头加一结尾减一遍历一遍判断奇偶数?
感觉第一题就是人车匹配,可以bfs也可以heap
第一题面试官说bfs太慢了。。第二题面试官问有没有比O(N) 快的方法
第一题给个例子吧,第二题如果是要确认所有的灯Output 不就O(n)了?如果是像my calendar系列那样一个function change state一个function check,用segment tree或binary index tree把change state和check state都做到log(n)

领我进门的中国小哥。面经上看到过,应该好好写一遍。 {a, b}c{d,e}f 需要return 所有可能的组合,acdf,acef,bcdf,bcef。followup 怎么处理 nested case:    a{b{c, d}e{f}}

这个题哪位同学有例题链接求贴

移除石头 + string deduplication + bingo game + skip iterator

SETI Onsite,MTV, Fail
Provider: null

第一轮:白女,LC 947 remove marble,不过输入可以自己定义,我定义的输入是个二维矩阵,好写一点。
http://massivealgorithms.blogspot.com/2018/11/leetcode-947-most-stones-removed-with.html
思路:没什么好说的,直接dfs,本来想用union find,但是面试官明确想让我用dfs去找connected components。写完面试官表示code写得很不错,然后没有follow up

当时写的白板代码:
int count;
int totalCount;
int rows;
int cols;
int[][] graph;
// 0是空格,1是marble
int removeMarble(int[][] graph) {
// sanity check, 这里只是说了下corner case,面试官说不用写
rows = graph.length;
cols = graph[0].length;
this.graph = graph;
for(int i = 0 ; i < rows;  i++) {
for(int j = 0 ; j < cols ; j++) {
if(graph[i][j] == 1) {
dfs(i, j);
count++;
}
}
}
return totalCount - count;
}
void dfs(int row, int col) {
totalCount++;
graph[row][col] = 0;
for(int i = 0 ; i < rows ; i++) {
if(graph[i][col] == 1) {
dfs(i, col);
}
}
for(int j = 0 ; j < cols ; j++) {
if(graph[row][j] == 1) {
dfs(row, j);
}
}
}
1. 给一堆职员及其老板的关系,要求实现两个query: A. 输入职员姓名按顺序返回其老板chain B. 输入老板姓名,按顺序返回职员chain

思路:
看起来像常规的建图和搜索

2. 给一个长长的String,String里面有一些char是separator,给一个isSeparator函数可以调用判断是不是separator。separator将该String分成若干部分,判断每部分是不是一个valid password。定义一个valid的password就是长度在6-10的string,包含两个以上的数字和字母。求所有valid password的数目。

思路:Two Pointers


3. google doc 有个comment 功能,每个comment是个tuple(int A,int B)。A表示是指向正文中哪一行的comment, B表示当前comment实际显示在正文对应的哪一行。要求实现用户在前一行插入一个comment后如果space不够了,后面的comment自动下移。

4. 国王住在King's Landing, 他手下有很多的信使,他要发布一项消息给所有的kingdoms,派信使去送信。问通知完所有的kingdoms所需要花费的最长时间。

5. 给两个文件,一个文件A很长,另一个文件B记录的是bad words。要求把文件A里面所有match的文件B里面的bad words替换成掉。

(Provider: anonymous, 匹兹堡office)
第二题:
给一个路径列表,找出每个路径在列表里的parent路径。例子:exports = [“/a/b/c”, “/abc/foo”, “/a”, “/abc”, “/a/b”, “/foo/abc”],return [[“/a/b”, “/a”], [“/abc”], [], [], [“/a”], []]
思路:建立trie,在node里有map of children和boolean isValid。然后遍历exports,到最后一个node把isValid设为true。再遍历exports,如果碰到isValid为true的parent node就把当前string加入结果。时间复杂度O(m*n),m为路径个数,n为每个路径里“/”的个数。

第三题:
删除二叉树中多余的一个edge。假设input是root node,而且删完edge后还是root。
例子: 1
         / \
        2 3
      / \ /
    4 5
删除2-5或3-5都可以
follow up: 如何测试?

思路:从root开始遍历,建立set保存visited node,如果碰到有node的儿子已经在set里就删除这个edge。(lc 685的超级简化版)

第四题:
面经题,给定宽为w高为h的screen,和一句话string,还有字体的上限和下限,问能使这句话fit进screen的最大字体。有两个写好的api分别是getWidth(Character c, int font), getHeight(int font)。

思路:二分法找median font,然后parse string看能不能fit进screen。
刚刚面完的Onsite
new grad SETI Sunnyvale

lc 484 find permutation

第一轮:
印度小哥
第一题:给一个pattern “IIDDI”, D代表decrease, I代表increase,找出能满足这个pattern的由数字1到n组成的值最小的Permutation,n=pattern.length+1,比如上面这个例子结果就是125436
思路:
先将原数组升序排列,满足了所有的I, 然后对于连续的D,全部reverse

code:
class Solution {
   public int[] findPermutation(String s) {
       int len = s.length();
       int[] res = new int[len + 1];
       for(int i = 0 ; i < res.length ; i++) {
           res[i] = i + 1;
       }
       for(int i = 0 ; i < len ; i++) {
           if(s.charAt(i) == 'D') {
               int j = i;
               while(j < len && s.charAt(j) == 'D') j++;
               reverse(res, i, j);
               i = j - 1;
           }
       }
       return res;
   }
   private void reverse(int[] arr, int left, int right) {
       int l = left, r = right;
       while(l < r) {
           swap(arr, l++, r--);
       }
   }
   private void swap(int[] arr, int i, int j) {
       int tmp = arr[i];
       arr[i] = arr[j];
       arr[j] = tmp;
   }
}

二叉树找最多siblings的层

第二题:给一个二叉树,找maximum size of level which has the largest number of siblings。这里sibling的定义就是从这一层的左端点到右端点的所有存在或者不存在的node,也就是假设这中间的Parent都有左右孩子的情况下,从左端点到右端点总共有多少个。

思路:
利用完全二叉树的index性质,按层遍历,记录每层起始node的index和末尾的index,相减后得到的距离,然后更新最大值

code:
Provider: null
private class MyNode {
int idx;
TreeNode node;
public MyNode(TreeNode node, int idx) {
this.node = node;
this.idx = idx;
}
}
public int maxSiblings(TreeNode root) {
if(root == null) return 0;
int res = 0;
Queue<MyNode> queue = new LinkedList<>();r
queue.offer(new MyNode(root, 1));
while(!queue.isEmpty()) {
int size = queue.size();
int first = queue.peek().idx;
while(size-- > 0) {
MyNode curr = queue.poll();
if(curr.node.left != null) {
queue.offer(new MyNode(curr.node.left, curr.idx * 2)); //如果树比较高,会很快溢出的
}
if(curr.node.right != null) {
queue.offer(new MyNode(curr.node.right, curr.idx * 2 + 1));
}
res = Math.max(res, curr.idx - first + 1);
}
}
return res;
}

棋盘上铺多米洛骨牌

lc 790 follow up poj 2446
第二轮:
中国大哥
给一个2*n的board,每个格子有两种情况,为空或者被block了。现在有大小为1*2的多米诺骨牌,问这个board最多能放多少个骨牌

思路:
动态规划
dp[i] 表示[0, i] 的最多骨牌
case 1: i列上没有block
dp[i] = dp[i - 1] + 1;
case 1.1: 如果dp[i-1]也没有block
dp[i] = max(dp[i], dp[i-2] + 2)
case 2: i列上有一个block
dp[i] = dp[i-1]
case 2.1: 如果i-1列上没有block or i-1上有一个block在同侧
dp[i] = max(dp[i], dp[i-2] + 1)
case 3: i列上有两个block
dp[i] = dp[i - 1]
这道题面经是我贡献的,为了不让大家觉得这道题难得过分以及花太多时间在这道题上,我想具体说明一下。根据面试时面试官给我的信息,这道题能够用greedy或者dp做出2*n的情况就已经非常不错了,如果你能答出m*n的思路当然非常加分,但是即使不知道也完全没关系,更不用要求能写出代码了。我自己在面的时候也只是在面试官的帮助下写出了dp,followup完全是面试官自问自答lol,最后还是过了HC。所以希望大家不用太panic,时间有限的情况下可以不用太在意followup

followup: board的size为m * n


思路:
二分图的最大匹配,匈牙利算法
对于一张二维矩阵,我们可以将所有cell分为两个点集,(x, y), x+y为奇数,x+y为偶数。
其中x+y为奇数被4个x+y为偶数包围,x+y为偶数被4个x+y为奇数包围,所以一条多米诺骨牌其实就是链接两个点集中的一条匹配边,这个题目就可以转化为删除两个点集中的一些点,求剩下点集的最大匹配,用匈牙利算法。

code
provider: null
   // board[i][j] = 1 -> blocked, 0 -> unblocked
   List<List<Integer>>point;
   int rows;
   int cols;
   int[][] board;
   int[] link;
   boolean[] used;
   public int chessBoard(int[][] board) {
   // init parameters
    this.board = board;
    rows = board.length;
    cols = board[0].length;
    point = new ArrayList<>();
    link = new int[rows * cols];
    used = new boolean[rows * cols];
    for(int i = 0 ; i < rows * cols ; i++) {
    point.add(new ArrayList<>());
    }
    for(int i = 0 ; i < rows ; i++) {
    for(int j = 0 ; j < cols ; j++) {
    if(i - 1 >= 0 && board[i-1][j] == 0) {
    point.get(i * cols + j).add((i - 1) * cols + j);
    }
    if(i + 1 < rows && board[i + 1][j] == 0) {
    point.get(i * cols + j).add((i + 1) * cols + j);
    }
    if(j + 1 < cols && board[i][j + 1] == 0) {
    point.get(i * cols + j).add(i * cols + (j + 1));
    }
    if(j - 1 >= 0 && board[i][j - 1] == 0) {
    point.get(i * cols + j).add(i * cols + (j - 1));
    }
    }
    }
    Arrays.fill(link, -1);
    // hangary algorithm
    return hangary();
   }
   boolean find(int x) {
    for(int i = 0 ; i < point.get(x).size() ; i++) {
    int vertex = point.get(x).get(i);
    if(used[vertex]) continue;
    else {
    used[vertex] = true;
    if(link[vertex] == -1 || find(link[vertex])) {
    link[vertex] = x;
    return true;
    }
    }
    }
    return false;
   }
   int hangary() {
    int ans = 0;
    for(int i = 0 ; i < rows ; i++) {
    for(int j = 0 ; j < cols ; j++) {
    if(board[i][j] == 0) {
    Arrays.fill(used, false);
    if(find(i * cols + j)) {
    ans++;
    }
    }
    }
    }
    return ans;
   }

判断表达式是否合法

第三轮:
中国小哥
第一题:给一个表达式算术1+2*(3-4),判断它是否合法,可能出现的字符就是数字、运算符、括号和其他非法字符。先要求提出一些比较模糊的case比如(0)、+5然后自己定义它们是否合法,然后问如果有人写好这么一个程序,你会用哪些test case来测试它,最后implement。

思路:
感觉就是考想出来所有corner cases

第二题:有一个填满了的数独board,已知有且只有一个数字填错了,且这个数字还是在1-9之间,找出这个填错的数字的坐标。


第四轮 直接扔给我一张纸,一开始看到题目是懵逼的 ,输入是一堆线段,找所有可以形成的正方形的数量,自己设计数据结构和算法。clarify之后如下,平面无限大,线段都是水平或者竖直,不会cross,但端点可能在另一个线段上。解法大概是枚举对角线,然后check四条边,但是不能直接check每一条边是不是在input 的线段当中,因为可能正方形的一条边是由多个input线段组成的,或者完全被包含在某一个线段当中,所以需要对所有x和y值建segment tree,然后每一个查四条边是不是完全被当前坐标的segment tree cover

有没有同学可以分享一下思路,如何用线段树判断一段距离都被cover了

思路:不用线段树的操作,建立两个并查集来merge水平和垂直方向上坐标相同的点。 初始状态是一堆输入的线段就可以认为是并查集的初始状态。

LC Car Fleet (频率 8)


第三轮比较简单,给一个Integer,n,形成一个List<Integer>,包含1-n的所有元素,每个元素代表一辆车的车速,最后会形成车队,要返回的是每个车队的车数。举个例子,[2,4,1,3],最后返回的是[2,2],因为前两辆车会被第一辆车的车速2所限制,而后两辆车则会被第三辆车的车速1限制。再举个例子,[1,2,3,4,5],最后返回[5]。[2,4,5,3,1],返回[4,1]。
Follow-up是在原List<Integer>插入n+1,然后返回所有的车队车数可能性。最后问了算法复杂度

思路:
感觉比原题 car fleet还要简单一些,直接从前往后扫一下,如果cars[i-1] < cars[i], cars[i] = cars[i-1],然后分别统计连续的数字个数

最大化连续子串最小sum (LC 410)


有一个数组,分成K部分,要求, min of subarray sum is maximized,   [1,2,4,3,3] 分成3部分, 你可以分成 1| 2,4|3,3 最小数组 是1, 但是你分成 1,2 |4|3,3 最小的数组sum就变成了3.  3是想要的答案。 这个我提出了DP和recursive, 面试官都不满意, 最后用的是二分查找. 比如说你给 一个数 N , 看这个数组能不能被分成K部分, 每个部分都大于N,  如果不能,就试试N/2。

思路:
如题主描述
这个题应该可以用binary search 解,思路与 lc410 相似

矩阵填字符

一个矩阵,里面有空字符和abc等character,用最近的字符填满矩阵。
A      ‘’  ‘’ ‘’        ‘’
‘’       ‘’ ‘’        ‘’ ‘’
‘’       ‘’ ‘’        B ‘’
空字符填上最近字符,有tie的话随便选一个
follow up:char比空字符多

思路:
先扫一遍得到有哪些字符,然后对每个字符best-first search, 用min heap当queue,heap里面装
Node{
int i; int j;
char c; int distance;
}
根据distance来决定优先级,距离小的在前面,每次poll出来一个新node看那个位置上有字符没有,没有的话填上,有的话忽略

code
Provider: null
  public void fillMatrix(char[][] matrix) {
    int rows = matrix.length;
    int cols = matrix[0].length;
    Queue<Node> pq = new PriorityQueue<>((a, b) -> a.dis - b.dis);
    for(int i = 0 ; i < rows ; i++) {
    for(int j = 0 ; j < cols ; j++) {
    if(matrix[i][j] != ' ') {
    pq.offer(new Node(i, j, matrix[i][j], 0));
    }
    }
    }
    int[][] dirs = new int[][] {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
    while(!pq.isEmpty()) {
    Node curr = pq.poll();
    if(matrix[curr.i][curr.j] == ' ') {
    matrix[curr.i][curr.j] = curr.c;
    }
    // generate
    for(int[] dir : dirs) {
    int x = curr.i + dir[0];
    int y = curr.j + dir[1];
    if(isValid(matrix, x, y) && matrix[x][y] == ' ') {
    pq.offer(new Node(x, y, curr.c, curr.dis + 1));
    }
    }
    }
   }
   private boolean isValid(char[][] m , int i, int j) {
    return i >= 0 && i < m.length && j >= 0 && j < m[0].length;
   }
   private static class Node{
    int i; int j; char c; int dis;
    public Node(int i, int j, char c, int dis) {
    this.i = i;
    this.j = j;
    this.c = c;
    this.dis = dis;
    }
   }
不需要用priority queue吧,简单的queue就可以了

Merge K Sorted Lists + Meeting Room II

第一轮:
1. 输入一些subiterators, 合成一个superiterator, 都是升序的. 类似LC 23 Merge k Sorted Lists. heap搞定.
2. LC 253 Meeting Rooms II

第四轮:

中国小哥哥。
4, 5, 6, 8
5, 5, 6, 9
6, 7, 9, 10
红色表示目的地. 问题是要找出能到所有目的地的点. 可以从其它任何点出发, 上下左右四个方向,, 只能往小于等于当前值的点挪(8可以去6, 但6不可以去8, 5可以去5). 图中绿色点就是答案. 刚开始对题目有一些问题, 后来小哥哥给了提示, 说是目的地不多. 后来就决定反着来了, 看从目的地开始能反着到哪些点, 存成set. 再用每一个点试, 如果在所有的set里就表示从这个点出发能到所有的目的地. 假设k个目的地, m行n列, 复杂度是O(kmn). 然后问如何并行. 对每个目的地都可以单独做, 我以为是O(mn), 但其实复杂度最高的地方是最后的test部分. 把所有的set放到一台机器上复杂度还是O(kmn). 类似merge sort, set也应该两两merge. 最后能优化到O(logkmn). 谢谢小哥哥了.
这题是不是LC417, BFS可以达到O(kmn)
类似,另外能不能用一个int[][] matrix来记录(i,j)能到达target的数量,就是从target bfs时候每到一个点matrix(i,j)+1,最后看matrix哪几个点的数字是target的个数?感觉可以不用每一个bfs一个存一个set
第五轮:
模拟抓娃娃机。
color      count
Green:   3 3个绿娃娃
Blue:      5
Red:       2
随机抓, 哪个颜色的数量多, 那个颜色被抓的概率也相应的高. 抓完要把相应颜色的数量减去1.
类似LC 528 Random Pick with Weight, 但不同点在于每次要减去1. 开始用数组, 二分查找O(logn), 更新O(n). 面试官没让写O(logn)的, 写个O(n)的就行. 写完了说想想能不能把更新的部分也优化一下. 我知道要用segment tree, 但想不起来了, 还是不太熟练. 主要是一直在想用用数组实现的方式, 卡在坐标变换上了. 面试官提示说还是用tree node吧, 好想一些. 请参考: https://leetcode.com/problems/ra ... n-with-segment-tree . 我觉得应该也把左右子树的sum放在node里. 面试官就是看看我怎么想的, 说是知道不太好写.

Tree Isomorphism Problem LC951(频率7)

1.一开始是个白人老大哥,跟我闲聊了差不多10分钟,介绍了他们组的项目,问我对于google什么项目感兴趣,然后看时间差不多了,出题
题目是check which two tree are similar, 就是一个function, 就是 1 - 3 - 2 和 1 -2 -3 就是similar, 然后follow up问我recursion的runtime,
我太紧张了硬是没有答出来  具体题目看连接 https://www.geeksforgeeks.org/tree-isomorphism-problem/ 估计我就是挂在这里

思路:
dfs,经典题目

两个string找多出来的char


2.第二题是个东南亚老大哥 亚裔,贼严肃,也不说话,上来就说题目, 然后题目是 给你两个string s1 s2, s2会比s1多一个char,
要你找出来那个char的index 比如 today, todxay, return 3
O(1) space better than O(N) time,我想了半天,巧妙一点的二分,follow up是如果两个string 乱序怎么办,就先sort
思路:
如果没有duplicate的话,根据时间空间复杂度要求自然联想到二分查找:
在长的string上二分
mid = l + (r - l) / 2
每次比较长的mid位置上的char和短的mid位置上的char是否一样,因为最多只会被插入一个字符,一样的话,说明左边部分没被插入东西,target一定右边,否则target在左边

注意:空串需要特殊处理,不然charAt会抛异常

如果有duplicate,感觉无法better than O(N),一个极端例子dddddddddd, dddddddddde,如果不check每个位置的话,无法找到多余的那个字符

code
Provider: null
  public int findExtra(String s1, String s2) {
    if(s1.length() == 0) return 0;
    if(s2.length() == 0) return 0;
    String longer = s1.length() > s2.length() ? s1 : s2;
    String shorter = s1.length() > s2.length() ? s2 : s1;
    int l = 0, r = longer.length() - 1;
    while(l + 1 < r) {
    int mid = l + (r - l) / 2;
    if(longer.charAt(mid) == shorter.charAt(mid)) {
    l = mid;
    } else {
    r = mid;
    }
    }
    if(longer.charAt(l) != shorter.charAt(l)) return l;
    else return r;
  }


def find_extra(str1, str2):
   if len(str1) > len(str2):
       str1, str2 = str2, str1
   lo, hi = 0, len(str1)
   while lo < hi:
       mid = (lo + hi) >> 1
       if str1[mid] != str2[mid]:
           hi = mid
       else:
           lo = mid + 1
   return lo

Binary Tree Vertical Order Traversal #LC 314 and LC 987


3.中午一个白人小姐姐带我吃了饭,下午第一轮是个中国大哥,贼亲切,一上来就用中文跟我打招呼,说接下来我们说题目用英文吧
我说好, 题目是 col order tree traversal,就是 一个tree       1 - 2 -3 root 的col是0 left leaf是-1, right leaf 是1
没有follow up跟我中文闲聊了十分钟,真的很感谢,说是自愿来当面试官,希望为华人也多分担一些,给华人学生多一些机会

思路:
  1. preorder标记每个node的vertical和level坐标,用map存,或者自定义类
  2. 如果同一个position上的node也有顺序的话还得排序

代码:主要思想是map + BFS,map可以对key进行排序
provider: (please fill your name)
class Solution {
public:
   vector<vector<int>> verticalOrder(TreeNode* root) {
       vector<vector<int>> res;
       if (!root) return res;
       queue<pair<TreeNode*, int>> q;
       q.emplace(root, 0);
       
       map<int, vector<TreeNode*>> m;
       
       while(!q.empty()) {
           int len = q.size();
           for (int i = 0; i < len; i++) {
               auto tmp = q.front();
               q.pop();
               m[tmp.second].push_back(tmp.first);
               if (tmp.first->left) q.emplace(tmp.first->left, tmp.second - 1);
               if (tmp.first->right) q.emplace(tmp.first->right, tmp.second + 1);
           }
       }
       
       for (auto ele : m) {
           res.push_back(vector<int>());
           for (auto node : ele.second) {
               res.back().push_back(node->val);
           }
       }
       return res;
   }
};


Random Pick With Weight #LC 528


4. 最后一轮来了两个大哥, 有一个是面试官trainee???, 第一题是 设计一个tree ??? 一天三道tree。。。 然后写个function level order traversal
第二题是 给你个rand() return 0,1之间的随机值,要你随机从一个dataset中取数据, 就是假如说数据里面有300个美国,100个中国,100个韩国,那么
这个function output 美国的概率就是3/5 etc

思路:
见lc

王位继承(10+频率)+歌词找单词+sign tree+找重复元素

第一轮 王位继承 美国小姐姐  这轮感觉还可以

第二轮 给两个 string 分别是lyric 和 word,问能不能用lyric 构成 word
比如 lyric "HIT ME BABY ONE MORE TIME" word = "BOOM" 那么是可以的
follow up 是优化时间
第三轮 给两个 tree, root1 root2, 问计算结果等不等
tree 里面只有 加号 和 字母, 并且 input 保证valid.
加号就是hashmap统计词频
减号是dfs的时候把sign传进去?

这题加了减号,不是一般的麻烦,类似basic计算器的那题,而且还不好合并,那道题是数字,这题是字母
传sign可以,然后如果是负数,可以存小写字母的对应大写(如果全是小写的话,如果不是,就自定义个映射),最后还是比较hashmap

第四轮 LC 287 find duplicate number
给一个数组长度为n+1,包含从1到n到数字,有重复元素,找出重复元素
开始没反应过来  后来才反应过来的。
follow up 就是优化空间,牺牲时间。
最后 他直接说告诉你这个 想看看我写binary search 看我的code implement ability

思路:
  1. 初始解法:用set(可以先装一波没见过)
  2. 如果数组可以改变,用heap sort可以做到o(1)空间 o(nlogn)时间
  3. 如果数组不可以改变,可以提出最优解 - 快慢指针找环和找环的入口,不过这里可能会被问到证明找环的入口的算法正确性,略麻烦
  4. 面试官期待的binary search 做法,o(1)空间,O(nlogn)时间,不改变数组
对值域进行二分[1, n],如果count出来小于等于mid数字个数比mid多,说明dupliate在mid左边,反之小于等于mid的数字个数等于mid或者比mid少,duplicate在mid右边
Code
Provider: 九章算法
public int findDuplicate(int[] nums) {
       int l = 1;
       int r = nums.length - 1;  // n
       
       while (l + 1 < r) {
           int mid = l + (r - l) / 2;
           if (count(nums, mid) <= mid) {
               l = mid;
           } else {
               r = mid;
           }
       }
       
       if (count(nums, l) <= l) {
           return r;
       }
       return l;
   }
   
   private int count(int[] nums, int mid) {
       int cnt = 0;
       for (int item : nums) {
           if (item <= mid) {
               cnt++;
           }
       }
       return cnt;
   }


二叉树删除多余边 (频率 13)


第一轮是一个比较严肃的美国小哥,题目不难但我太紧张导致脑子短路: 一个binary tree里有1个extra edge,找到并且fix。我用dfs做的,然后写完小哥让我自己找我的code能不能cover所有的情况, 然后发现并不能,改了几下之后code终于能work。反正这轮磕磕绊绊,要挂就挂在这了。

完全树数node(频率 5)

第二轮是个超酷的打耳钉的美国小姐姐。高频题LC222,先给你一个数,找这个数在不在tree里面,followup找到树的大小。这轮真是 使尽各种演技。。。

http://massivealgorithms.blogspot.com/2015/06/leetcodecount-complete-tree-nodes.html

用路径string找word

第三轮美国小哥,题目很长很绕但交流之后其实很简单,简洁地表述下大概就是:用户在手机屏幕上滑动打字, 给你一串string记录了你手指滑动经过的char,举个例子比如, “hrwcewelwlcfo”, 这个手指滑动可以打出一个”hello”。用户从h开始,手指划过“rwc”, 打出一个“e”, 划过”we“, 打出”l“, 划过w, 打出”l“, 再划过”cf“, 打出“o”. 这样就打出“hello”,很神奇有没有??

然后给你一个路径的string和一个dictionary of words, 问你有多少个word可以被用这个路径打出来。路径的第一个字符和最后一个字符一定是会被打出来的。这题本质很简单基本靠交流。 我说了两种方法,一种从路径入手,排列组合,一个一个放到dictionary里面查;另一种一个一个word拿出来,two pointer比较。比较了两种方法的复杂度,还算了一些数学公式,写了第二种的code。followup是如果在同一个位置可以停留多次怎么做,就是在同一个char上可以重复打好多次。比如“hwelpto”也可以打出“hello”,这里“l”重复打了两次,也不难,秒了。

lc853原题car fleet

第四轮印度哥, 是sweti,题也很简单,一列车队n辆车,速度分别是1到n,随机排列成一条,然后开始开,不能超车,问你无限时间之后return一个车队cluster array,每个数代表cluster里车的个数,要按顺序。比如input【2, 3, 1, 4】返回的是【2,2】。一开始我以为他要问cars fleet那题,没想到问了个更简单的。。。follow up是现在有一辆车speed是n+1,我们把它加入到这个n车车队的空隙中,总共n+1个空隙,然后问你每种加入,最后导致的车队cluster array,就是return一个array of array。写完followup之后讨论怎么test。

House Robber III (频率 5)

思路:见LC337,返回两个结果的recursion函数

抽搐词(lintcode twitch words)

返回重复超过三次的letter的起点和终点
Example
Given str = "whaaaaatttsup", return [[2,6],[7,9]].

Explanation:
"aaaa" and "ttt" are twitching letters, and output their starting and ending points.

follow up:给一个dic,通过删除生成合法的词语

思路:backtracking


Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts