Sunday, January 13, 2019

Google interview questions - Round 2 - #3 - 他人汇总


https://www.1point3acres.com/bbs/thread-467093-1-1.html

https://docs.google.com/document/d/1qxA2wps0IhVRWULulQ55W4SGPMu2AE5MkBB37h8Dr58/edit?usp=sharing

---------------------
https://www.1point3acres.com/bbs/thread-446944-1-1.html


莉蔻三九九及其变种(汇率)
频率:21
就是一个2维数组里的有人和自行车,要每个人匹配到一辆自行车,人和自行车的距离越短越好,没有距离相同的情况。就是算出所有的距离然后放到heap里慢慢pop出来,记录下人和车的状态就可以了。
频率:13
 再跟一下

利口六八四 六八五及其变种(bst删除额外边)
频率:10
-baidu 1point3acres
利口六二
著名变种:DP。给定一个矩形的长宽,用多少种方法可以从左上角走到右上角 (每一步,只能向正右、右上 或 右下走):整个矩形遍历做DP即可,不需要想复杂. 牛人云集,一亩三分地
Solution
public static void main(String[] ss) {


    System.out.println(ways(7, 6));
}

public static int ways(int m, int n) {
    int[][] dp = new int[m + 2][n];
    dp[1][0] = 1;

    for (int i = 1; i < n; i++) {
        for (int j = 1; j < m + 1; j++) {
            dp[j][i] = dp[j - 1][i - 1] + dp[j][i - 1] + dp[j + 1][i - 1];
        }
    }

    return dp[1][n - 1];
}
-follow up:如果给矩形里的三个点,要求解决上述问题的同时,遍历这三个点 (切割矩形,一个一个地做DP,然后相加)
Solution, 所有路径必须经过这3个点,求一共有多少种走法(到达右上)
其实这3个点跟起点和终点没有区别。如果存在这3个点,则这5个点中的任意2个点不可能存在在一个column上。按column来划分矩形,分别对两两做dp
可以写一个方法
int ways(int m, int n, int[] start, int[] end, int startCount) 来避免代码重复

-follow up:如何判断这三个点一个是合理的,即存在遍历这三个点的路经
Solution
2个相邻之间的点的连线与水平线的夹脚 <= 45度,就可以说明左边的点能到达右边的点。表示为 |y2 - y1| >= x2 - x1, 假设(x1, y1) (x2, y2) 为左右2点

-follow up:如果给你一个H,要求你的路径必须向下越过H这个界,怎么做 (别问我,我不会)
Solution
找出不越界的路线个数,原来的结果相减就得到越过的个数

楼主这题试一试用镜像做,也就是说重点不在(W, 0), 而在(W, 2H), W是矩阵的宽度
频率:9
六口把四散(猜词)
843
频率:9


莉蔻八就灵及其变种(word pattern)
890
频率:8

六口死罢就(扫地机器人)-baidu 1point3acres
489
频率:7

莉蔻八五五及其变种(考试找位子)
855
频率:6

带expiration的hashmap
频率:6
Solution:
value存上timestamp
2个方法:1.主动去清空 2. 读写的时候对比timestamp

多个不重复的长方形内重复取点
follow up:多个可能重复的长方形内随机取点
频率:6
497, follow up:先把长方形都分割好

莉蔻八五三(高速路车分cluster)
频率:5
853

莉蔻八五期(雇工人)
频率:5


六口气五菱(matrix里找长方形)
频率:5
利口把衣物及其变种(公交路线)
频率:5
利口六五九及其变种(找顺子)
频率:5
给一个国王家的family tree (n-ary tree),王位继承是先传国王最年长的儿子,假如最年长儿子死了,就传给死儿子最年长的儿子。。。如果这些人都不存在,再考虑国王次年长的儿子,以此类推。要求设计这样一棵树,死掉的人不要求删除,实现birth()和输出王位继承顺序的method(死掉的人不在继承顺序结果里)。(及其变种)
频率:5
Tree Isomorphism Problem (search in geeksforgeek)
频率:5
给定一个multiple tree,以及需要删除的多个nodes,要求返回一个node的list,以便在nodes被删除之后可以找到这些nodes的child。
例子:. Waral 博客有更多文章,
a. From 1point 3acres bbs
/ / \ \. From 1point 3acres bbs
b d c f. Waral 博客有更多文章,
/ \ \.1point3acres网
h z i
假如删除b和f,返回{a, d, c, h, z, i}
假如删除a和b,返回{d, c, f, h, z, i}
可以用level traverse解。
频率:5
. 1point3acres
可乐饮料机,有一系列按钮,每个按钮按下去会得到一定体积范围的可乐。先给定一个目标体积范围,问不限制按按钮次数,能否确定一定能得到目标范围内的可乐?
举例:有三个按钮,按下去得到的范围是[100, 120], [200, 240], [400, 410],
假设目标是[100, 110], 那答案是不能。因为按下一,可能得到120体积的可乐,不在目标范围里。
假设目标是[90, 120],那答案是可以。因为按下一,一定可以得到此范围内的可乐。
假设目标是[300, 360], 那答案是可以,因为按下一再按二,一定可以得到此范围内
假设目标是[310, 360], 那答案是不能,因为按下一再按二,有可能得到300,永远没可能确定得到这个范围内的可乐。
假设目标是[1, 9999999999],那答案是可以。随便按一个都确定满足此范围。
频率:5


如果有用,请加米,多谢!



补充内容 (2018-10-3 09:35):
multiple tree那道题貌似栗子错了,应该是删除bf的话返回ahzi
. 1point3acres
补充内容 (2018-10-3 09:42):
落了一道题:
判断target字符串是否可以由给定字符串转换得到。转换的规则是:每次转换要变所有的相同字母
比如:abca -> cdec 可以 abca -> abea -> cbec -> cdec
频率:5

补充内容 (2018-10-4 00:53):
这里统计的面经从三四月到九月,lz面试遇到的所有的题里面有三道题出自这个高频题。还有两道是频率为3的没有放到这里。面经见另外一个帖子。

补充内容 (2018-10-4 07:05):
多个不重复的长方形内随机取点,不是重复取点

补充内容 (2018-10-10 11:49):
频率为34的在此
http://www.1point3acres.com/bbs/thread-448608-1-1.html



-----------------------------------
https://www.1point3acres.com/bbs/thread-448608-1-1.html


频率4
1. 下围棋,判断棋盘上一个点是不是被包围了。
用了dfs 写的挺顺的。 然后问testcase, 画了各种形状的围棋图
2. 一个map分为n层,每层都m个node, 每个node有值,每一层跟下一层的node是full connected,edge的值不一定相同,求从第一层到最后一层的mini cost
3. ABC 小哥和大黑哥, 问了一个拿纸牌游戏, 纸牌上面有值,比如说 100, 1, -1, 2, 200, 1. 然后两个人轮流拿,直到拿完。 但是每次只能拿从左边数起的前三个,但是如果你要拿第三个,就必须前两个都拿了,你要拿第二个,就必须第一个也拿了,大家都最优策略,问最后第一个人能拿多少分。dfs 加 cache做了。
4. 一个image以2D byte array的方式储存(byte[][] image),每个象素点是1个bit(0或1)。现在要求每行的象素点做对称翻转。我的做法是先把每行的byte对称翻转,然后再把每个byte各自翻转。

如其中一行byte[] row = {11010100,00101010}
第一步{00101010,11010100}
第二步{01010100,00101011}
时间复杂度是O(m*n*8), follow up如何优化时间,应该是在翻转每个byte上把O(8)的复杂度降低,但是不要求使用复杂的位运算
5. 已知screen的高和宽,给你最小和最大的fontSize,要求给定一个string,将string用竟可能大的fontSize显示在screen里。已知两个API getHeight(int fontSize), getWidth(char c, int fontSize),可以得到每个character在不同fontSize下的高和宽。和面试官交流后,确认string可以拆分成几行显示在screen中,先提出暴力解法,然后用二分法优化.
6. 莉蔻把零散 (打砖块)
7. 莉蔻儿五三及其变种(meeting room). From 1point 3acres bbs
8. random generate a maze
9. 白人大哥,给一个list intervals of integer ([2,9], [1,3], [10,20] ..), 给一个integer X, 查找X在不在给的interval 里面。答曰一遍遍历,o(n). 他问能不能优化。这个list 是无序的,只有排好序才能优化,但是排序就要o(nlogn)。在我追问下,他说了如果我们有很多的查询x在不在,能不能优化每次的查询?那就是一次性处理这个list intervals. 我先给的解法是遍历一遍intervals, 把所有数字存到hashset里,查询用hashset, O(1)。他貌似对这个解法不满意,说这个方法如果数字很大,很占内存,等等。我就顺着他说先sort, 然后binary search. binary search 前要先remove overlap.然后开始写代码。
10. 实现一个iterator的iterator

频率3 (很神奇,大多都是莉蔻原题变种)
1. 离扣留气流各种变种
2. 莉蔻把四九
3. 莉蔻丝一把
4. 离扣留吧
5. 莉蔻把丝丝. From 1point 3acres bbs
6. 莉蔻三九思
7. 莉蔻三三四
8. 莉蔻琪琪死
9. 利口三三期
10. 粒扣三丝翎
11.设计个log start,finish finish后 输出log id跟内容 但finish的时候 如果start前面还有start 就不能输出
直到没有pending了 就全输出
比如
start(1, time1)
start(2, time2)
start(3, time3). 牛人云集,一亩三分地
finish(2, time2)
finish(3, time3)
finish(1, time1) . check 1point3acres for more.
输出 1, 2 ,3
为啥 因为finish2得时候 前面还有个1 被start过
finish3的时候 2虽然没了 前面还有个1 被start过
12. 莉蔻斯八六
13. 莉蔻儿药物
14. 粒扣三一而
15. 莉蔻气流就
16. 莉蔻舞领舞
17. 利口酒流
18. 莉蔻把三丝


------------------------------
https://www.1point3acres.com/bbs/thread-429386-1-1.html


第一题:矩阵从左上角到右下角有多少种走法
给定一个矩形的长宽,用多少种方法可以从左上角走到右上角 (每一步,只能向正右、右上 或 右下走)
Follow up 1:如果给矩形里的三个点,要求解决上述问题的同时,经过这三个点
Follow up 2:如何判断这三个点一定是合理的,即存在路径
Follow up 3:如果给你一个H,要求你的路径必须向下越过H这个界,怎么做
Follow up 4:要经过某些特定row怎么走?要先经过一个row再经过另一个row怎么走?
. From 1point 3acres bbs
感觉可以第一问用two pass DP解决。Follow up 1和2可以纵向切割矩阵,一个矩阵一个矩阵做DP。
但是Followup 3&4我就不太会了,该咋做呢~




第二题:01矩阵走路问题
0和1的grid,1是墙,0是路,从左上角走到右下角,最少多少步。
Follow-up: 现在说能把grid中的一个1变成0,问新的最小步数是多少步。

第一问应该就是常规的DP。第二问不知道该怎么做~




第三题:User CPU Peak问题
给了一堆log,log里有用户id,resource id以resource在某个起始时间和终止时间的使用量,比如用户abc在1到5秒钟使用了CPU的数量是2,用户abc在2到3秒使用的CPU数量是4,也就是一个用户对某个resource的使用在某个时间是可以叠加的,给定一个resource id,根据用户对这个resource的peak使用量,找到top k的用户。上面的例子中abc的CPU的peak使用量是2+4=6
Follow up:如果数据量很大怎么办。

感觉可以把占用resource id的user id对应log聚合在一起,但是怎么计算这个peak就想不通了,感觉跟Meeting room有点像?但不知道该怎么实现。



第四题:拿卡片游戏
每张卡片都有一个值,给定一堆卡片从一头拿,每次可以拿一到三张,两人轮流拿,求最高得分。考虑卡片值为负的情况。

这个用DP?DFS?



第五题:是男人就跳问题
给一个二维坐标平面和一个起始点,从这点开始垂直下跳,下面有若干水平挡板,位置长度会在input里给,板的形式是(x, y, distance),当跳到挡板上时,可以选择走到挡板的左端或者右端,然后继续垂直下跳,直到落地位置,求从开始到落地需要走过的路程最短是多少。

懵逼中,有大神能讲讲做法吗~



第六题:找到一条线将坐标系中的点分成两等份
题目是在一个坐标系里给很多离散的点,找到一条线将所有点分成两个数量相等的集合,不用考虑基偶性或者多个点在一条线上的特殊情况。

这是啥。。楼主数**渣。。



第七题:随机生成一个Candy Crush
黑人问号脸?有大神能详细描述下题目吗?




补充内容 (2018-6-11 11:33):
第二题解法有问题,由于可以随便走,所以应该用BFS,而非DP

678. Valid Parenthesis String

678Valid Parenthesis String
Given a string containing only three types of characters: '(', ')' and '*', write a function to check whether this string is valid. We define the validity of a string by these rules:
  1. Any left parenthesis '(' must have a corresponding right parenthesis ')'.
  2. Any right parenthesis ')' must have a corresponding left parenthesis '('.
  3. Left parenthesis '(' must go before the corresponding right parenthesis ')'.
  4. '*' could be treated as a single right parenthesis ')' or a single left parenthesis '(' or an empty string.
  5. An empty string is also valid.
Example 1:
Input: "()"
Output: True
Example 2:
Input: "(*)"
Output: True
Example 3:
Input: "(*))"
Output: True
Note:
  1. The string size will be in the range [1, 100].
------------------------
ref: https://leetcode.com/problems/valid-parenthesis-string/discuss/107577/Short-Java-O(n)-time-O(1)-space-one-pass

遇到'*'可以生成3种可能) = -1, "" = 0, ( = +1。 另一关键在于所有的可能性都是连续的 0, 1, 2,....
保持一个最小最大,如果最后最小能到0,说明可以获得合法的string
class Solution {
    public boolean checkValidString(String s) {
        int low = 0, hi = 0;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (c == '(') {
                hi++;
                low++;
            }else if (c == ')') {
                if (low > 0) {
                    low--;
                }
                hi--;
            }else if (c == '*') {
                if (low > 0) {
                    low--;
                }
                hi++;
            }
            if (hi < 0) return false;
        }
        
        return low == 0;
    }
}

Saturday, January 12, 2019

# Knapsack

0-1 背包问题
问题:给大小为n的数组weights[]和values[], 求在不超过W的情况下能取得的value总和最大是多少,每一个数只能最多取一次(或者不取)

本质是排列组合,复杂度O(2^n)
public static void main(String[] ss) {

        int[] a = {1,2,3};
        int[] b = {4,2,1};
        int w = 3;

        System.out.println(knap(a, b, w));

    }

    private static int maxValue = 0;
    private static int knap(int weights[], int values[], int maxW) {
        dfs(weights, values, 0, 0, 0, maxW);
        return maxValue;
    }


    private static void dfs(int[] weights, int[] values, int curV, int curW, int index, int maxWeight) {
        if (curW > maxWeight) {
            return;
        }

        maxValue = Math.max(maxValue, curV);
        for (int i = index; i < weights.length; i++) {
            dfs(weights, values, curV + values[i], curW + weights[i], i + 1, maxWeight);
        }
    }

另一种写法。这种写法更容易看出我们可以用[index, curW] = weight来标记每一个状态(递归树上的结点)
O(2^n)
    private static int knap(int weights[], int values[], int maxW) {
        return dfs(weights, values, 0, 0, maxW);
    }

    private static int dfs(int[] weights, int[] values, int curW, int index, int maxWeight) {
        if (index == weights.length) {
            return 0;
        }
        int max_1 = 0;
        if (curW + weights[index] <= maxWeight) {
            max_1 = dfs(weights, values, curW + weights[index], index + 1, maxWeight) + values[index];
        }
        int max_2 =  dfs(weights, values, curW, index + 1, maxWeight);
        return Math.max(max_1, max_2);
    }

Memoization
O(maxW * n)
private static int knap(int weights[], int values[], int maxW) {
        int n = weights.length;
        int[][] dp = new int[n][maxW + 1];

        return dfs(weights, values, 0, 0, maxW, dp);
    }

    private static int dfs(int[] weights, int[] values, int curW, int index, int maxWeight, int[][] dp) {
        if (index == weights.length) {
            return 0;
        }

        if (dp[index][curW] != 0) {
            return dp[index][curW];
        }
        int max_1 = 0;
        if (curW + weights[index] <= maxWeight) {
            max_1 = dfs(weights, values, curW + weights[index], index + 1, maxWeight, dp) + values[index];
        }
        int max_2 =  dfs(weights, values, curW, index + 1, maxWeight, dp);
        int rt = Math.max(max_1, max_2);
        dp[index][curW] = rt;

        return rt;
    }

iterative dp, 通项公式跟递归是一摸一样
O(maxW * n)
private static int knap(int weights[], int values[], int maxW) {
        int n = weights.length;
        int[][] dp = new int[n][maxW + 1];

        for (int i = 0; i < maxW + 1; i++) {
            if (weights[0] <= i) {
                dp[0][i] = values[0];
            }
        }

        for (int i = 1; i < n; i ++) {
            for (int j = 1; j < maxW + 1; j++) {
                if (j - weights[i] >= 0) {
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - weights[i]] + values[i]);
                }else {
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }

        return dp[n - 1][maxW];
    }
可以发现当前的dp[row]只依赖于之前一行dp[row - 1], 所以可以简化为一维dp
    private static int knap(int weights[], int values[], int maxW) {
        int n = weights.length;
        int[] dp1 = new int[maxW + 1];
        int[] dp2 = new int[maxW + 1];

        for (int i = 0; i < maxW + 1; i++) {
            if (weights[0] <= i) {
                dp1[i] = values[0];
            }
        }
        
        for (int i = 1; i < n; i ++) {
            for (int j = 1; j < maxW + 1; j++) {
                if (j - weights[i] >= 0) {
                    dp2[j] = Math.max(dp1[j], dp1[j - weights[i]] + values[i]);
                }else {
                    dp2[j] = dp1[j];
                }
            }

            int[] tmp = dp1;
            dp1 = dp2;
            dp2 = tmp;
            Arrays.fill(dp2, 0);
        }

        return dp1[maxW];
    }

Unbounded knapsack
如果按0-1的解法的话会形成3个嵌套的for循环
换一种思路
 , 
O(n * maxW)
private static int knap(int weights[], int values[], int maxW) {
        int n = weights.length;
        int[] dp = new int[maxW + 1];

        for (int i = 1; i < maxW + 1; i++) {
            for (int j = 0; j < n; j++) {
                if (i >= weights[j]) {
                    dp[i] = Math.max(dp[i], dp[i - weights[j]] + values[j]);
                }
            }
        }

        return dp[maxW];
    }
       

ToDo
可以用贪心算法吗?v / w 最大的那个一直加

Bounded knapsack

322. Coin Change 518. Coin Change 2

322Coin Change
You are given coins of different denominations and a total amount of money amount. Write a function to compute the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return -1.
Example 1:
Input: coins = [1, 2, 5], amount = 11
Output: 3 
Explanation: 11 = 5 + 5 + 1
Example 2:
Input: coins = [2], amount = 3
Output: -1
Note:
You may assume that you have an infinite number of each kind of coin.
---------------------------
DP, 遍历1 - amount每一个数,找出该数所需要的最小个数
dp[i] 存的是在amount i下最小所需要的个数
class Solution {
    public int coinChange(int[] coins, int amount) {
        
        int[] dp = new int[amount + 1]; 
        Arrays.fill(dp, amount + 1);
        dp[0] = 0;
        
        for (int i = 1; i <= amount; i++) {
            for (int j = 0; j < coins.length; j++) {
                if (coins[j] <= i) {
                    
                    dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1);
                }
            }        
        }
        
        return dp[amount] == amount + 1 ? -1 : dp[amount];
    }
}

Solution #2, memoization
class Solution {
    public int coinChange(int[] coins, int amount) {
        
        int[] mem = new int[amount + 1]; 
        mem[0] = 0;
        
        return rec(coins, amount, mem);
    }
    
    private int rec(int[] coins, int amount, int[] mem) {
        if (amount < 0) return -1;
        if (amount == 0) return 0;
        if (mem[amount] != 0) return mem[amount];
        
        int min = Integer.MAX_VALUE;
        for (int c : coins) {
            int count = rec(coins, amount - c, mem);
            if (count != -1) min = Math.min(min, count);
        }
        
        if (min == Integer.MAX_VALUE) mem[amount] = -1;
        else  mem[amount] = min + 1;
        
        return mem[amount];
    }
}


518Coin Change 2
You are given coins of different denominations and a total amount of money. Write a function to compute the number of combinations that make up that amount. You may assume that you have infinite number of each kind of coin.

    Example 1:
    Input: amount = 5, coins = [1, 2, 5]
    Output: 4
    Explanation: there are four ways to make up the amount:
    5=5
    5=2+2+1
    5=2+1+1+1
    5=1+1+1+1+1
    
    Example 2:
    Input: amount = 3, coins = [2]
    Output: 0
    Explanation: the amount of 3 cannot be made up just with coins of 2.
    
    Example 3:
    Input: amount = 10, coins = [10] 
    Output: 1
    

    Note:
    You can assume that
    • 0 <= amount <= 5000
    • 1 <= coin <= 5000
    • the number of coins is less than 500
    • the answer is guaranteed to fit into signed 32-bit integer
    ---------------
    dp[i] 是在amount i时的number of combination,则最后结果返回dp[amount]
    通项公式
    dp[i] = dp[i - coins[0]] + dp[i - coins[1]] + ... + dp[i - coins[coins.length - 1]] if i - coins[0] >= 0

    class Solution {
        public int change(int amount, int[] coins) {
            int[] dp = new int[amount + 1];
            dp[0] = 1;
            
            for (int i = 0; i < coins.length; i++) {
                for (int j = 1; j < amount + 1; j++) {
                    if (j >= coins[i]) {
                        dp[j] += dp[j - coins[i]];
                    }
                }
            }
            
            return dp[amount];
        }
    
    }
    

    Wednesday, January 9, 2019

    Morris traversal

    https://www.geeksforgeeks.org/inorder-tree-traversal-without-recursion-and-without-stack/

    本质上是inorder的traversal。把当前结点的左儿子的最右的叶子结点(也就是在inorder顺序上,当前结点的前一个结点)的右结点指向当前。当第2次到达这个结点的时候,可以重新给断开
    时间跟空间都是 O(1)
    void morris(TreeNode root) {
    
        TreeNode cur = root, pre = null;
        while (cur != null) {
            if (cur.left != null) {
                pre = cur.left;
                while (pre.right != null && pre.right != cur) {
                    pre = pre.right;
                }
    
                if (pre.right == null) {
                    pre.right = cur;
                    cur = cur.left;
                }else {
                    System.out.println(cur.val);
                    cur = cur.right;
                    pre.right = null;
                }
            }else {
                System.out.println(cur.val);
                cur = cur.right;
            }
        }
    }
    
    
    Morris traversal iterator
    public class OA {
    
        public static void main(String[] ss) {
            Node n50 = new Node(50);
            Node n40 = new Node(40);
            Node n30 = new Node(30);
            Node n1 = new Node(1);
            Node n35 = new Node(35);
            Node n45 = new Node(45);
            Node n60 = new Node(60);
            Node n55 = new Node(55);
    
            n50.left = n40;
            n50.right = n60;
            n60.left = n55;
            n40.left = n30;
            n40.right = n45;
            n30.left = n1;
            n30.right = n35;
            
            MoItr itr = new MoItr(n50);
    
            for (int i = 0; i < 8; i++) {
                System.out.println(itr.next());
            }
        }
    
        static class MoItr{
    
            private Node root;
            public MoItr(Node root) {
                this.root = root;
            }
    
            public int next() {
    
                while (root != null) {
                    if (root.left != null) {
    
                        Node pre = root.left;
                        while (pre.right != null && root != pre.right) {
                            pre = pre.right;
                        }
    
                        if (pre.right == null) {
                            pre.right = root;
                            root = root.left;
                        }else {
                            int rt = root.val;
                            pre.right = null;
                            root = root.right;
                            return rt;
                        }
    
                    }else {
                        int rt = root.val;
                        root = root.right;
                        return rt;
                    }
                }
    
    
    
                return -1;
            }
    
        }
    
    }
    
    

    Monday, January 7, 2019

    Google interview questions - Round 2 - #2

    https://www.1point3acres.com/bbs/thread-469613-1-1.html

    468673

    1. 原点有一个modem,周围有N台设备用两个X和Y坐标数组给出,求第K近的设备并将距离取上整返回,类似荔筘蛾药毋,只不过那题是第K大,这是第K小
    LC215

    2. Meeting Room II 基本是原题,只是interval给的是Start和End的两组数组,但是思路是一样的
    LC 253

    ----------------------------
    https://www.1point3acres.com/bbs/thread-469425-1-1.html

    第一轮:
    1. 给 array A B, 输出去掉A B中所有重复元素的array。for example: ([1,1,1,1,2,3], [1,2,4])-->[1,1,1,3,4]。一开始用了两个dictionary/hashmap,follow up 要求仅使用一个
    一个map
    public static void main(String[] ss) {
    
            int[] a = {1,1,1,5,6,1,2,3};
            int[] b = {1,2,4,9,6,6,1};
    
            System.out.println(removeDup(a, b));
    
        }
    
        public static List<Integer> removeDup(int[] a, int[] b) {
            Map<Integer, Integer> m = new HashMap<>();
    
            for (int i : a) {
                m.put(i, m.getOrDefault(i, 0) + 1);
            }
    
            for (int i : b) {
                if (m.containsKey(i)) {
                    if (m.get(i) != 0) {
                        m.put(i, m.get(i) - 1);
                    }
                }else {
                    m.put(i, -1);
                }
            }
    
            List<Integer> rt = new ArrayList<>();
            for (Map.Entry<Integer, Integer> e : m.entrySet()) {
                for (int i = 0; i < Math.abs(e.getValue()); i++) {
                    rt.add(e.getKey());
                }
            }
    
            return rt;
        }
    

    2. Coin Change. 1point3acres
    LC322

    第二轮:
    1.Sequence Iterator
    2.写一个iterator, initialize的时候输入另一个list iterator,然后在另一个iterator的基础上实现hasNext和next:
    for example:
    初始化时候输入 [a,a,a,b,b,a]的iterator
    while(it.hasNext()):
        print(it.next())

    这段代码会输出 (a,3) (b,2) (a,1)
    这道题一开始讨论了半天没搞清题意,可能feedback不太好加面了一轮
    Solution:
    public static void main(String[] ss) {
    
            List<String> l = new ArrayList<>();
            l.add("a");
            l.add("b");
            l.add("b");
            l.add("c");
    
            Iterator<String> i = l.iterator();
            ItrHelper itr = new ItrHelper(i);
            while (itr.hasNext()) {
                System.out.println(itr.next());
            }
        }
    
        public static class ItrHelper{
    
            private Iterator<String> itr;
            private String cur;
            private boolean itrHasNext;
            public ItrHelper(Iterator<String> itr) {
                this.itr = itr;
                cur = null;
                itrHasNext = itr.hasNext();
            }
    
            public boolean hasNext() {
                return itr.hasNext() || itrHasNext;
            }
    
            public String next() {
    
                int count = 1;
    
                while (itr.hasNext()) {
                    String next = itr.next();
    
                    if (cur == null) {
                        cur = next;
                    }else if (cur.equals(next)) {
                        count++;
                    }else if (!cur.equals(next)) {
                        String rt = cur + " " + count;
                        cur = next;
                        return rt;
                    }
                }
    
                if (itrHasNext) {
                    itrHasNext = false;
                    return cur + " " + count;
                }
    
                return "";
            }
        }
    

    第三轮:

    1.感觉地里见过的,给两个string问第一个能否通过 暂时移走部分字符(总的顺序不能改变)+copy paste 构成另一个

    for example: 输入"BZAXYZ"和"ZAZABY",可以"BZAXYZ"+"BZAXYZ"+"BZAXYZ"="ZAZABY"

    最简单的办法就是判断是否第二个string中所有字符都在第一个中

    follow up: 输出最少需要几次暂时移走+copy paste才能完成

    这题写的太慢,

    follow up
    不断的找longest common subsequence,直到2个string相等

    ---------------------------------
    https://www.1point3acres.com/bbs/thread-469405-1-1.html


    大家好,楼主前几天去面了狗狗,准备了很久所以到了一月才面。。四轮面试两轮国人两轮天竺友人,想问一下第三轮这样的情况该怎么处理。

    第一轮,三姐,萦绕在我脑海中一个题目,要写两个function,后来优化,本来是o(n) o(n) 后来优化到了o(1) o(logn)。。但是我居然就是想不起来是什么了。。。面完大概早上10:45走的时候我对她说了个have a good night。。。抱歉没想起来

    -baidu 1point3acres

    第二轮,国人小姐姐,进来的时候刚好听到我对三姐说have a good night, 用中文说让我别紧张。。我顿时感动的啊,我面试还没见过中国人。。后来英文面的,是面鲸有过的题,给一个数组take snapshot,每次take snapshot后存一下当时的数组状况。后面会访问某一次snapshot时数组的值。
    得找一找题

    午饭,一个外国小哥哥,带我吃了饭还逛了下,回来的时候看到会议室已经坐了人了,门关着的,狗家那个会议室玻璃墙中间是模糊的,上面和下面是透明的。于是小哥就踮着脚去看里面是不是有别人在面试,我就蹲下来歪着头看里面有几条腿。。。然而小哥虽然比我高,但还是不够高,所以最后还是我发现了里面就一个人。。开门的时候看到是三哥,心里惊了一下。

    番外:我实习时候遇到的三哥都很好让我觉得三哥有很多好的,但是今年面fb全职和去年面fb实习遇到的三哥都好狠,让我害怕被他们面。就是很rude,经常问一些莫名其妙的问题,有时候发现不重要的错漏就盯着不放,一直耗在那里,浪费我时间。。所以fb实习和全职都一轮电面挂了。。都只做出来了一题。。因此我就很害怕谷歌面试遇到三。俗话说的好,怕啥来啥。。

    第三轮,三哥,题目就一句话,让我先随机构造一颗size为N的树。我开始没听到“random”一词,就以为构成一颗树就行。秉着论坛经验贴说的,要提前考虑各种条件。我就开始问他,有木有其他限制,比如形状有木有要求,普通的树还是二叉树,N<=0怎么办等等。。。他就说没有,只要size是N就行了。(我后来知道是random的时候,我觉得他这时候应该高速告诉我要random,他就一开始说了一遍题目,我也没听到random这个词,我觉得他可能当时说了我没注意。。但到了这里,我问过他这些各种边界条件后,我很确定他这次说的是只要N就行)

    然后我就开始边说边写,先写了个平衡树,因为觉得这样子左右子结点个数比较好算。完了他说为什么是这样的树勒?我就说了一下,他说你这样只能返回一种类型啊,不是landom的,我要landom的。(请脑补他们说的llllandom,不是rrrrrrrandom....emmmmm)这都是小事,后面才尴尬了。

    我就开始random了,我本来写的是每一棵root节点的左子树有rand.nextInt(0,N)个数个子结点,右子树就是N-1-numOfLeft,然后递归构造这棵树。我本以为这是随机的,但是试了下N=3的case,发现并不是。。N=3应该有五种可能,概率都是1/5,我的这个方法概率都是1/6。然后三哥就说你这个概率是不是不对呢?我说是啊,是不对,想了会儿没想好怎么改,就问他hint,他就说你这个概率不对,你应该找到正确的概率。。我就继续看,我就发现了左子树1个节点的时候这一个节点只有一种排列方法,但是左子树2个节点的时候就有两种可能的排列方法了。也就是说我的算法其实把“根节点-一个左子结点-一个右子结点”这样的情况返回概率是2/6,其他四种概率都是1/6. 发现了这里我就想先把unique subtree的个数算出来好了,这种就可以得出每一种tree占全部的概率了。。但我有点动摇,就有问他有木有other hints,他就说你yeah, i do,然后告诉我这个概率不对,你应该找到正确的概率(这就是前一个hint啊...摔! )。。我以前lc上做过一个题目就是用dp算n个节点树的形状的可能性的,我就和三哥说了,打算先用dp把1-n个节点可以构成的树的形状个数都算出来。三哥说你把关键代码写一下,别写所有的了,我就打算只从for开始写,他说你别写for了,直接写公式好了。。我想了一下,这不写for怎么看得懂公式勒?公式需要用到for循环里的参数啊。。但是我还是先按照他说的只写公式,后来发现不行,我就自作主张还是把for写了。写完他说算的是对的。

    然后他就一直在问然后你怎么算出正确的概率呢?我就在说,让我想一下分子分母应该分别是dp[几],然后他也一直在问。。我心里从landom那里就不淡定了,一直在想着要挂。后期阶段他又一直在旁边说无关痛痒的话,我心里就乱乱的,想了一下没确定分子分母该是哪个,他又说我没时间了,让我问他个问题,就结束了。

    代码也没写多少,就一开始递归构造平衡树那个代码,加一个dp公式,还有些画的不同类型的树和一些草稿。。他拍了照。

    还有他全程几乎都坐在椅子上看杀父仇人一样看着我,和他说话什么也没什么反馈,就全程黑着脸,问他hint了好几次他也都只是说我概率不对,并没有和其他面试官那样和我“交流问题&解法”的态度。我一看就知道要挂我。。毕竟和之前两次fb电面的天竺哥哥惊人的相似,全程不怎么踩我,盯着一个破绽就一直问问问。

    Solution
    类似96. Unique Binary Search Trees DP的方法 ,有待证明

    第四轮:国人小哥,n-ary tree里面的最长路径。

    Solution
    只有1个leaf的时候算root+这个leaf的距离
    public static void main(String[] ss) {
    
            Node root = new Node('A');
            (root.child).add(new Node('B'));
            (root.child).add(new Node('F'));
            (root.child).add(new Node('D'));
            (root.child).add(new Node('E'));
            (root.child.get(0).child).add(new Node('K'));
            (root.child.get(0).child).add(new Node('J'));
            (root.child.get(2).child).add(new Node('G'));
            (root.child.get(3).child).add(new Node('C'));
            (root.child.get(3).child).add(new Node('H'));
            (root.child.get(3).child).add(new Node('I'));
            (root.child.get(0).child.get(0).child).add(new Node('N'));
            (root.child.get(0).child.get(0).child).add(new Node('M'));
            (root.child.get(3).child.get(2).child).add(new Node('L'));
    
            maxPath(root);
            System.out.println(max);
        }
    
        public static  class Node{
            public char key;
            public List child;
            public Node(char key) {
                this.key = key;
                this.child = new ArrayList<>();
            }
        }
    
        static int max = 0;
        static int maxPath(Node root) {
            if (root == null) return 0;
    
            int max1 = 0, max2 = 0;
            for (Node c : root.child) {
                int path = maxPath(c);
                if (path > max1) {
                    max2 = max1;
                    max1 = path;
                }else {
                    max2 = path;
                }
            }
    
            max = Math.max(max, max1 + max2 + 1);
            return Math.max(max1, max2) + 1;
        }
    

    ---------------------------------
    https://www.1point3acres.com/bbs/thread-469256-1-1.html

    Sunnyvale

    第一轮:国人小哥,leetcode原题应该,求最长valid parenthesis 有O(n)解法
    LC32
    第二轮:香港(?)小哥,比较基础,给一个数组,还有int top要你实现栈的pop()函数,double linkedlist删除节点,很基础知识,最后还问了一个sort的问题,但是就说了几句,时间就到了

    第三轮:国人小姐姐,面经原题,patition n task into k days to minimize the amount of resources used per day, usage per day is the same, task must be completed sequentially
    得找一找

    第四轮:国人小哥,给你一个string和list of change(class change{int offset, string before, string after}), 来实现string的更新,follow change无效有几种情况,分别怎么处理

    只能想到最笨,最直接的解法


    ---------------------------------
    https://www.1point3acres.com/bbs/thread-469219-1-1.html
    一个已经sort 过的数组。[1,2,3,4,5,6,7] for example.
    把它变成一个,偶数位的数字要大于所有这个位置之后的数字。 奇数位的数字要小于所有这个位置之后的所有数字。
    上面那个例子变形之后应该是[7, 1, 6, 2, 5, 3, 4]
    follow up如果数组没有sort 过呢?
    Solution
    public static void main(String[] ss) {
    
            int[] n = {1,2,3,4,5,6,7};
            int[] rt = reorder(n);
            for (int i : rt) {
                System.out.print(i + " ");
            }
    
        }
    
        static int[] reorder(int[] nums) {
            int n = nums.length;
            int left = 0, right = n - 1;
            int[] rt = new int[n];
    
            for (int i = 0; i < n; i += 2) {
                rt[i] = nums[right];
                if (i + 1 < n) rt[i + 1] = nums[left];
                left++;
                right--;
            }
            return rt;
        }
    

    ---------------------------------
    https://www.1point3acres.com/bbs/thread-469186-1-1.html

    第一轮 白人小哥。猜词游戏,写一下如何判断player猜词的score(guess word 和 secret word中相同char的个数),然后如何根据history判断guess word是不是good guess。
    843

    第二轮 白人小哥。给一个state machine的图,每个节点是一个state,问某一个节点是不是唯一可以走到success state。可以有多条路,但是必须都通向唯一的success state。 dfs秒了,优化到O(N) ,大哥让我找找更快的方法,我想了半天硬着头皮说 worst case还是要访问所有节点, 真的不知道还有什么方法了, 可以hint吗?大哥很开心的告诉我对的没有更快的方法了。然后还剩十分钟写了个Top K。
    题意不清。如果success state定义是只有incoming edge, 没有outgoing edge话,那么recursion的base case就可以按照这个来写。或者是要知道对terminating state的定义

    午餐 白人小哥,聊得挺开心的。午餐的鸡腿不错。

    第三轮 白人小哥。套了个外壳,不过题目大意是,有一个数组,分成两个subarray,求所有的两个subarray的差值。注意是所有的,不是求最小差值。做题前问问题clear了一些条件,subarray可以是empty的,元素是1-10000的int,想起来了再补充。


    第四轮 白人大叔(老爷爷),给一个string,相邻两个字母如果分别是同个字母的大小写,就删掉这个pair。example: aBbA 返回aA. 然后follow up是可以递归消除 aBbA 返回“”. 然后又扯了一个big integer的实现什么的没说完就到时间了。老爷爷人很好,一直笑眯眯的,后来我没写完他跟我说这是你的homework。
    Solution
    public static void main(String[] ss) {
    
            String s = "CaeEAC";
            System.out.println(deleteSame(s));
        }
    
        static String deleteSame(String s) {
            Stack st = new Stack<>();
    
            for (int i = 0; i < s.length(); i++) {
                char c = s.charAt(i);
                if (!st.isEmpty() && compareTwo(c, st.peek())) {
                    st.pop();
                }else {
                    st.push(c);
                }
            }
    
            String rt = "";
            while (!st.isEmpty()) {
                rt = st.pop() + rt;
            }
            return rt;
        }
    
        static boolean compareTwo(char c1, char c2) {
            return Math.abs(c1 - c2) == 32;
        }
    

    第五轮 白人小哥。 类似于一个设计题。有一个游戏,每个player做不同的任务有不同得分,每三十秒统计一次得分最高的人,整个游戏结束后返回在任意三十秒得分最高的<player,得分, 开始时间>的一个tuple。这轮的小哥全程低头敲代码记录,不管问什么都是好好好对对对up to you。最后我写完了以后,他问我怎么优化,然后扯了cpu cache,大哥讲兴奋了在纸上写写画画给我讲了一堆cpu 优化的事儿,想不起来一个名词非要查清楚告诉我,最后还跟我说别紧张这些都不是面试内容,就是希望我会这些就pretty cool。

    思路
    1.  写2个java executor, 一个用来每30s排序,另一个用来跑player的game(这个可有可不有)
    2. 或者



    总体感觉是五个白人小哥都挺...不太能聊的,但是感觉都很聪明。题都做出来了,交流也还可以,但是感觉有点凉,挂点是第一轮最后要了一些提示,第四轮没写完big integer的东西,这个不知道是老爷爷临时起意还是算是面试内容,第五轮真的太累了,一开始分析问题没太说清楚,后来缓过来改了一些思路,我跟小哥说,对不起我真的太累了,刚才脑子当机了,他说没事的我也经历过,这一天太漫长了,后来也跟我说我解决的pretty fine,不过感觉他过程中态度不积极,可能不是很满意。



    抱歉哈第三轮没有说清楚,把原array分成两个之后,求两个subarray中的元素的和的差值 math.abs(sum(sub1) - sum(sub2))



    ---------------------------------
    https://www.1point3acres.com/bbs/thread-468795-1-1.html
    感恩节海投的简历年底才收到OA, 拖了一周在今天01/02才胆战心惊地做了。不小心一个小bug改了一个小时才改出来。

    幸好最近的题目改过之后还没变 还是黎扣215和253


    ---------------------------------
    https://www.1point3acres.com/bbs/thread-469613-1-1.html
    12月 17号面的, 今天刚刚收到onsite的通知。 题目是 leetcode 317 . 略微有些改动, 中间加了些 blocks 用2表示。我当天一面完晚上就在 leetcodes上碰到这道题了,不知道算不算不幸。

    心得: 多跟面试官交流 做题的时候一定以跟面交流的为主, 我当时做的时候的方法 在LeetCode上做 就超时了,但是当时面的时候面试官觉得我的方法复杂度okay.

    并且,还犯了个可大可小的错误,我知道要写bfs, 定义的辅助函数名字也是 bfs, 但是当时太紧张,条件反射的写了个dfs的body。写到最后我意识到我写的东西是dfs。我跟面试官说

    面试官也意识到了,但是由于时间原因,他让我继续完成主函数了,就没改。 比较尴尬。


    ---------------------------------


    https://www.1point3acres.com/bbs/thread-468694-1-1.html

    第一轮 sorting network 第一问 写一个算法验证一个sorting network working correctly, 第二问假设可以开无数条线程,需要多少步可以用一个给定的sorting network排完序

    Zero One princple, 如果任意一个由{0,1}组成的数列可以被sort,则可证明sorting network是可行的
    http://staff.ustc.edu.cn/~csli/graduate/algorithms/book6/chap28.htm
    Follow up: 是线性的


    第二轮 有一对box,给定这些box的长和宽,放在坐标轴上,每个box之间要满足一个hgap和一个vgap,让最后所占用的面积最小

    题意不清
    错误:本质上应该就是排列组合,每2个box形成一个新的box,再随机取第3个box又形成一个新的。
    枚举的应该可以解


    第三轮 利口 溜散吴 利口久柏
    635, 98


    第四轮 第一问给定一个triangle sort,让他变成正常顺序的
    2分找奇点,线性复制。或者全部用线性

    第二问给一个list of (start, end, speed),start和end表示位置,计算出从0-last position的每一段的平均速度. 你可以想象成一条x轴,start是一个x轴上一个点,end是x轴上另一个点,然后这条线段上有一个平均速度。。。input是一个list的这样的线段,会有很多overlap。。。。最后要的output是把x轴上的每一段平均速度都输出出来
    Solution#2
    怎么想都是O(n^2), 把重复的地方都给切分成单独小段,然后可以指定给对应的线段。
    最后对每一条线段做整合
    上面的复杂度跟暴力解是一样的:对每一条线段,都遍历整个list

    加面

    第一问,有放回的从一个桶里拿不同颜色的球,保证每次随机拿出一个球,返回该球的颜色

    第二问,如何测试我的算法是不是正确-baidu 1point3acres

    第三问,有放回的从桶里拿球,保证每次随机拿出一个球,返回该球的颜色

    ---------------------------------
    https://www.1point3acres.com/bbs/thread-468628-1-1.html

    第一轮 一个华裔,题目是找一个以第一个str的后缀和第二个str的前缀match的最长str
    ex: hellow owabc 这个就返回2
    本质就是kmp
    public static void main(String[] ss) {
            String s1 = "hellowcd";
            String s2 = "owcdabc";
    
            int l = Math.max(longest(s1 + s2),
                    longest(s2 + s1));
    
            System.out.println(l);
        }
    
    
        static int longest(String s) {
            int n = s.length();
            int[] table = new int[n];
            int j = 0, i = 1;
    
            while (i < n) {
                if (s.charAt(i) == s.charAt(j)) {
                    table[i] = j + 1;
                    i++;
                    j++;
                }else if (j > 0) {
                    j = table[j - 1];
                }else {
                    i++;
                }
            }
    
            return table[n - 1];
        }
    

    第二轮 应该是个白人小哥。面经题,棋盘放旗子,第一列0-15,第二列15-30 每一个不能重复,follow up是如果有很多棋盘怎么办,以及怎么优化

    (感觉问怎么优化的时候说了几个常规的感觉面试官都不是很满意,一直问还有没有其他的)
    题目看不明白

    第三轮 应该是个中国大哥,以前从来没见过的题,很难描述,大致是几个函数,getValue(), left(), getParent(), getNext(), 走一遍这个tree的时候同事调用这几个function,然后传给另一个server,另一个server可以通过这几个function还原出这个树,问题是让你写出这几个function的实现。题目不太好理解,面试的时候花了一些时间去理解题目,理解了做出来就很快了。follow up忘记了,但是不难。
    题目看不明白,有人说是Morris

    午饭一个英格兰小哥,人很nice。吃完饭我建议回去休息吧,但是小哥非常想带我去散步,只能从了。。。


    第四轮 一个欧洲大叔,题目是一个str只用一步变为另一个str,然后把这个变换用一个str return回来。比如abc-》def 就是replace abc with def, abc-》a就是delete bc from a,abc-》abcd就是 add d to abc。这个题乍一看简单写起代码就没那么容易,还设计到ood,因为面试官的意思是让我设计一个类可以很好的封装三种操作,用枚举,但是枚举面试中英语怎么说我给忘了,非常尴尬。到最后勉强写完了。


    第五轮,韩国小哥,感觉这个小哥最不友好,出的题也是最难。一个n*n的迷宫,每个点都有四个门,中间有谢个障碍,一开始知道从起点到终点是不能通过的,求改变哪一个点的哪一个门的方向可以让从起点到终点可以通过。本来面了一天就已经非常累的,听到这个题直接晕倒。用bfs尽力写了,但是最后还是没有写完。
    题目看不明白
    门的方向可能是障碍。可以理解为取消一个障碍就能找到通路。算法是对每个障碍找到终点跟起点的通路,找到了就代表可以移除那个障碍。BFS可以做

    感觉面试偏难了,可能还是自己水平比较菜。而且狗家面试的时候面试官一直在我写代码的时候跟我说你只有多少时间了,心里就更紧张。面完两天hr就打电话了也没什么feedback就说比较mix,结果面完就知道了,第一轮和第五轮都答的特别不好。无论如何move on了已经。好好准备其他家面试!!

    ---------------------------------


    https://www.1point3acres.com/bbs/thread-468615-1-1.html


    1. m*n 的棋盘上有若干棋子,如果同一行或者同一列中还有别的棋子的话,则可以扔掉一个棋子,问最少棋盘上能剩多少棋子.
    LC 947

    2. 有expiration的字典.
    面经题

    3. 读有timestamp的文件,给一个起始和终止的时间,返回其中所有的信息

    4.给一个图和root,判断这个图是不是一个树.. 1point3acres
    UnionFind, 261, 684, 685. 

    5. 给一个只能读一个固定长度的块的函数, 设计一个可以读取任意指定长度的函数.
    157,158

    ---------------------------------
    https://www.1point3acres.com/bbs/thread-468605-1-1.html

    10月底MTV Onsite

    第一轮:国人大哥 求2个BST相同的元素 要求O1 space 强制要求写Morris Traversal Iterator 血跪。。。
    Solution
    public class OA {
    
        public static void main(String[] ss) {
            Node n50 = new Node(50);
            Node n40 = new Node(40);
            Node n30 = new Node(30);
            Node n1 = new Node(1);
            Node n35 = new Node(35);
            Node n45 = new Node(45);
            Node n60 = new Node(60);
            Node n55 = new Node(55);
    
            n50.left = n40;
            n50.right = n60;
            n60.left = n55;
            n40.left = n30;
            n40.right = n45;
            n30.left = n1;
            n30.right = n35;
            
            MoItr itr = new MoItr(n50);
    
            for (int i = 0; i < 8; i++) {
                System.out.println(itr.next());
            }
        }
    
        static class MoItr{
    
            private Node root;
            public MoItr(Node root) {
                this.root = root;
            }
    
            public int next() {
    
                while (root != null) {
                    if (root.left != null) {
    
                        Node pre = root.left;
                        while (pre.right != null && root != pre.right) {
                            pre = pre.right;
                        }
    
                        if (pre.right == null) {
                            pre.right = root;
                            root = root.left;
                        }else {
                            int rt = root.val;
                            pre.right = null;
                            root = root.right;
                            return rt;
                        }
    
                    }else {
                        int rt = root.val;
                        root = root.right;
                        return rt;
                    }
                }
    
    
    
                return -1;
            }
    
        }
    
    }
    
    第二轮:Snake and Ladder简化版 自定义数据结构 可以写一个1D array 用bfs
    909

    第三轮:给定0-1 Matrix 把1形成的岛的内部的1都变成0 只剩一个周长1
    把所有上下左右不是1的数做标记,然后第2次遍历给转换成0

    第四轮:给定数组 输出长度为k的increasing subsequence 要求nlogk。。。
    Solution,
    每次遇到长度增加后,跟之前的长度做对比,如果当前数字可以加入到之前的长度。比之前长度的末尾要小,就直接取array里面的。

    另一个方法就是每次加入到dp里面数字,都map到它之前的那个数字的index,最终可以用map串联起来

    public static void main(String[] ss) {
    //        int[] nums = {1,4,8,2,9};
            int[] nums = {1,4,8,2,1,2,3,4};
            System.out.println(lengthOfLIS(nums, 3));
        }
    
        static List<Integer> lengthOfLIS(int[] nums, int k) {
            int n = nums.length;
            int[] que = new int[n];
            int len = 0;
            List<Integer> pre = new ArrayList<>();
    
            for (int i = 0; i < nums.length; i++) {
    
                if (len == 0 || que[len - 1] < nums[i]) {
                    que[len] = nums[i];
                    len++;
    
                    if (pre.size() == 0 || nums[i] > pre.get(pre.size() - 1)) {
                        pre.add(nums[i]);
                    }else {
                        List<Integer> tmp = new ArrayList<>();
                        for (int j = 0; j < len; j++) {
                            tmp.add(que[j]);
                        }
                        pre = tmp;
                    }
                    
                    if (pre.size() == 3) return pre;
                }else {
                    binary(nums[i], que, len);
                }
            }
    
            return pre;
        }
    
        static private void binary(int target, int[] que, int len) {
            int left = 0, right = len - 1;
    
            while (left <= right) {
                int mid = (left + right) / 2;
                if (que[mid] >= target && (mid == 0 ||que[mid - 1] < target)) {
                    que[mid] = target;
                    break;
                }else if (que[mid] <= target) {
                    left = mid + 1;
                }else {
                    right = mid - 1;
                }
            }
    
        }
    


    第五轮:research

    过了2周送HC 再过2周HR打电话说fail 没有feedback。。

    补充内容 (2019-1-2 02:36):

    第四题是要求小于n^2 时间复杂度 类似LIS的题

    ---------------------------------
    https://www.1point3acres.com/bbs/thread-468403-1-1.html

    第一轮
    List<Interval>,isCovered(int idx),看idx是否被 list of interval 覆盖,说了如果insert新的interval怎么办
    sort + merge, 然后2分查找

    第二轮 expiring map
    面经题

    第三轮

    第一题:cat+dog = fish, 就三个string,每个char和digit(0-9)一一对应,找这样一个对应使等式成立 dfs(backtracking) 解决,worst cast 10!

    followup:提升, 可提升至 (10!/4!),把左边dfs出来,然后右边能不能assign对应的char即可
    Solution
    DFS + backtracking。如果只返回boolean的话代码会精简很多
    public static void main(String[] ss) {
    
            getMap("cat", "dog", "fish");
        }
    
        static void getMap(String s1, String s2, String a) {
            Map<Character, Integer> cToI = new HashMap<>();
            Map<Integer, Character> iToC = new HashMap<>();
            if (dfs(s1 + s2, 0, iToC, cToI,s1.length(), a)) {
                System.out.println(cToI);
                
            }
        }
    
    
        static boolean dfs(String s, int index, Map<Integer, Character> iToC, Map<Character, Integer> cToI,
                           int divider, String target) {
    
            if (index == s.length()) {
                return isValid(s, cToI, iToC, divider, target);
            }
    
            char c = s.charAt(index);
            if (cToI.containsKey(c)) {
                return dfs(s, index + 1, iToC, cToI, divider, target);
            }
    
            for (int i = 0; i < 10; i++) {
                if (iToC.containsKey(i)) continue;
                iToC.put(i, c);
                cToI.put(c, i);
                if (dfs(s, index + 1, iToC, cToI, divider, target)) return true;
                iToC.remove(i);
                cToI.remove(c);
            }
    
            return false;
        }
    
        static boolean isValid(String s, Map<Character, Integer> cToI, Map<Integer,Character> iToC, int divider, String target) {
    
            int sum = 0;
            for (int i = 0; i < divider; i++) {
                char c = s.charAt(i);
                sum = cToI.get(c) + sum * 10;
            }
    
            int cur = 0;
            for (int i = divider; i < s.length(); i++) {
                cur = cToI.get(s.charAt(i)) + cur * 10;
            }
    
            sum += cur;
            int n = target.length();
            int tmp = sum;
            int count = 0;
            while (tmp > 0) {
                tmp /= 10;
                count++;
            }
            if (n != count) return false;
    
            boolean flag = true;
            List<Character> extra = new ArrayList<>();
            for (int i = n - 1; i >= 0; i--) {
                char c = target.charAt(i);
                if (cToI.containsKey(c) && cToI.get(c) == sum % 10) {
                    sum /= 10;
                    continue;
                }
    
                if (cToI.containsKey(c) || iToC.containsKey(sum % 10)) {
                    flag = false;
                    break;
                }
    
                extra.add(c);
                cToI.put(c, sum%10);
                iToC.put(sum%10, c);
                sum /= 10;
            }
    
            if (!flag) {
                for (Character c : extra) {
                    iToC.remove(cToI.get(c));
                    cToI.remove(c);
                }
    
            }
    
            return flag;
        }
    



    第二题: 给一个树, 给一个api:boolean shouldBeDeleted(Node node)
    返回删除所有 should be deleted 节点后的森林
    不懂

    第四轮 一个2d array, A,可能涂黑或者没涂黑,read(x1,y1,x2,y2)会返回:
    全黑: 1 全白: -1, Mix:0,只能通过这个read api 来获取这个2d图的信息
    现在要给另外一个api: write(x1,y1,x2,y2),在一个空白的图上把A画出来
    Divide and conquer
    void copy(int rows, int cols) {
        draw(rows - 1, 0, 0, cols - 1);
    }
    
    void draw(int r1, int c1, int r2, int c2) {
        if (r1 <= r2 || c1 <= c2) return;
    
        int rt = read(r1, c1, r2, c2);
        if (rt == 1 || rt == -1) write(r1,c1,r2,r2,rt);
        else {
            int midR = (r1 + r2) / 2;
            int midC = (c1 + c2) / 2;
    
            draw(r1,c1,midR,midC);
            draw(midR + 1, c1, r2, midC);
            draw(midR + 1, midC + 1, r2, c2);
            draw(r1, midC + 1, midR, c2);
        }
    }
    

    第五轮
    第一题:给一个api,String getNameByIndex(int idx).如果有这个index,就返回name,如果没有index(这个index之后也没有index),就返回null.
    实现 Integer getIndexByName(String Name); 如果name存在就返回其index,如果不存在就返回null
    存一个map index -> name, 然后反过来name -> List of index, 如果name是按顺序存的,这时候可以用binary search

    第二题:给一堆Iterator of sorted Integer, 实现一个iterator of iterators,相当于merge sort出来
    类似23. Merge k Sorted Lists

    然后问了些基础知识
    问了BST和HashMap的区别和实现(没code)
    全程交流极好,面完整个人都膨胀了

    ---------------------------------
    https://www.1point3acres.com/bbs/thread-468398-1-1.html
    isPalidrome热身
    实现iterator(iterator, isPalidrome)
    给一个string list 的iterator,实现iterator只返回Palidrome的string
    存一个instance level的String,指向下一个palidrome。

    ---------------------------------


    https://www.1point3acres.com/bbs/thread-468318-1-1.html


    第一轮:面试官迟到15分钟, 给一个二叉树,里面是int, 求叶子节点的和。我说用recursion, 他让我把思路说一遍,然后问我时间空间复杂度, 讨论了一下树balance和不balance的区别。这时候有别人要用会议室,somehow我们就必须走,然后面试官现定了一个room,还是在楼下。尴尬的走下楼,到了问我不用recursion怎么做,我就说iterative + stack做,然后问我recursion/iterative优劣。 这时候还剩10分钟吧,他说now the interesting part begins...不用extra space怎么做,想了两三分钟没想出来,我就一直emm/well/interesting, 然后无助的看着他。他说加个parent pointer怎么样,我想既然能加variable,那就再加一个boolean flag called visited, 然后用parent + visited 遍历树怎么样,他说那就太简单了,然后又想了一分钟,想到用prev/cur,然后把算法讲了一遍,这时候时间到了而且我还得走回之前的会议室,小哥笑嘻嘻的说我照个相,我心想我一行代码没写你照个毛啊(全是画的各种图),真想把白板挡着不让他照。。这轮时间没有太延长,所以真正在面试的时间也就30分钟左右吧

    面完后才知道还有morris遍历这种算法,但是我觉得面试背着写下来也没啥意义吧。 我最后提的解法有点类似利口姚思武的interative解法,仅供参考。

    第二轮:类似利口流二, 从左下到右下,能走右上,右, 右下,写完让优化,就是有些区域没必要check, 因为永远走不到,加个if check一下就好了,我用dp做的. 1point3acres
    面经题


    第三轮:基本就是利口齐三柳, 只不过没有let, 只有add和mult。 从来没见过这题,因为我个人特别讨厌刷eval expression相关的题, 但是面试的时候就强迫自己冷静,一步步分析,最后写的代码跟标准的答案基本一样。这轮面试官感觉有点不耐烦,基本是说完题就开始抄我的代码和记笔记, 他的键盘声也搞得我有点无法集中

    736

    第四轮:给一个List<List<Integer>>, int offset, int count, return一个List<Integer> 表示从offset开始的count个数

    Example:

    list1: 1, 2, 3

    list2: 4, 5, 6

    offset: 2

    count: 3

    return 2, 3, 4

    直接找到开始的list, 然后往下数就好,这道题需要注意corner case, indexOutofbound之类的,我有个越界bug被指出来后改了
    双指针应该可以

    第二题 利口伞思柳, 写完聊了聊数太大overflow了怎么办. 1point3acres

    346

    第五轮:利口三舅舅,装傻三分钟然后讲解思路,巨工整写完,follow up问query太多了怎么办,我说加个cache。最后小哥很开心的送我下楼
    399


    ---------------------------------


    https://www.1point3acres.com/bbs/thread-468281-1-1.html


    系统设计


    Linux系统上设计一个文件copy。先要求单机单进程单线程。可以用任何系统调用。C++




    我的实现是:1,判断是否可以copy(鉴权,路径合法性,磁盘容量等) 这一部分他要求写comment就可以了,不用写代码;2,在求出源文件长度后,fopen打开源文件(读)和目的文件(写);分配new char* buffer[BLOCK],开始初始化,准备copy;3,while(true):read_size = fread(), write_size = fwrite(), 会有read_size < BLOCK (直接break), write_size != read_size的情况(ret_code = WRITE_FAILURE; goto END);4,退出3的循环后,再次检查total_write_size是否等于源文件长度;5,收尾:我用goto写的统一的收尾,释放buffer,fclose,最后return ret_code。




    这个写完后,先问了BLOCK设多少;copy到中途出现问题挂了怎么办。然后问了分布式读写的一些设计。






    ---------------------------------
    https://www.1point3acres.com/bbs/thread-468271-1-1.html
    第一面:汇率转换,似乎高频了一年,没想到还能面到。面试官小哥明确要求我用union find写。楼主写得磕磕绊绊
    399

    第二面:人车匹配,地里很多帖子都详细描述了。
    面经题

    第三面:王位继承,也有很多帖子详述。
    面经题
    public static void main(String[] ss) {
            String k = "king";
            Inh i = new Inh(k);
    
            i.birth("king","l1");
            i.birth("king","l2");
            i.birth("king","l3");
            i.birth("l1","l11");
            i.birth("l11","l111");
            i.birth("l2","l21");
            i.birth("l21","l211");
            System.out.println(i.getOrder());
            i.dealth("l11");
            i.dealth("king");
            System.out.println(i.getOrder());
        }
    
        static class Inh{
            private Node king;
            private Set<String> dead;
            private Map<String, Node> map;
    
            public Inh(String king) {
                this.king = new Node(king);
                dead = new HashSet<>();
                map = new HashMap<>();
                map.put(king, this.king);
            }
    
            public String getOrder() {
                List<String> rt = new ArrayList<>();
                dfs(king, rt);
    
                StringBuilder sb = new StringBuilder();
                for (String s : rt) {
                    sb.append(s).append(" ");
                }
    
                return rt.toString();
            }
    
            private void dfs(Node root, List<String> order) {
                if (root == null) return;
                if (!dead.contains(root.id)) {
                    order.add(root.id);
                }
    
                for (Node c : root.children) {
                    dfs(c, order);
                }
            }
    
            public void birth(String father, String son) {
                Node s = new Node(son);
                map.get(father).children.add(s);
                map.put(son, s);
            }
    
            public void dealth(String p) {
                dead.add(p);
            }
        }
    

    第四面:find relation。这道题在地里看过,但是似乎描述都不太详细,所以多说两句楼主面的版本:
    Given a collection of relations, find the relations between two people.
    A relation between two people (x and y) can be:
    - x manages y.
    - x is managed by y.
    - x is a peer of y.
    For simplicity, two people are peers if and only if they are managed by the same person.
    A person can have at most one manager. One's manager's manager is not his manager.
    Implement two methods: `is_peer(x, y)` and `is_manager(x, y)`.
    在一个有向图上做BFS就可以了。
    Solution
    2个map,employee -> manager,employee -> peers
    难点#1先处理上下的关系,#2dfs遍历所有上下关系的点,在处理平级之间的关系,用visited来去重

    ---------------------------------


    https://www.1point3acres.com/bbs/thread-468256-1-1.html


    还是email那题,不过变为找到重复最多的email有多少次




    第二题

    给一个int array,找到两个重复出现的数字最短的距离。

    比如 [4,3,5,6,3,5,4],最短的是3和5,距离都是4






    ---------------------------------

    Friday, January 4, 2019

    800. Similar RGB Color

    800Similar RGB Color
    In the following, every capital letter represents some hexadecimal digit from 0 to f.
    The red-green-blue color "#AABBCC" can be written as "#ABC" in shorthand.  For example, "#15c" is shorthand for the color "#1155cc".
    Now, say the similarity between two colors "#ABCDEF" and "#UVWXYZ" is -(AB - UV)^2 - (CD - WX)^2 - (EF - YZ)^2.
    Given the color "#ABCDEF", return a 7 character color that is most similar to #ABCDEF, and has a shorthand (that is, it can be represented as some "#XYZ"
    Example 1:
    Input: color = "#09f166"
    Output: "#11ee66"
    Explanation:  
    The similarity is -(0x09 - 0x11)^2 -(0xf1 - 0xee)^2 - (0x66 - 0x66)^2 = -64 -9 -0 = -73.
    This is the highest among any shorthand color.
    
    Note:
    • color is a string of length 7.
    • color is a valid RGB color: for i > 0color[i] is a hexadecimal digit from 0 to f
    • Any answer which has the same (highest) similarity as the best answer will be accepted.
    • All inputs and outputs should use lowercase letters, and the output is 7 characters.

    ---------------------
    Solution #1
    class Solution {
        private static int[] preset = {0,17,34,51,68,85,102,119,136,153,170,187,204,221,238,255};
        private static String[] hex = {"00","11","22","33","44","55","66","77","88","99","aa","bb","cc","dd","ee","ff"};
        public String similarRGB(String color) {
            String s = "#";
            for (int i = 1; i < color.length(); i += 2) {
                int min = 0;
                int cand = toInt(color.charAt(i)) * 16 + toInt(color.charAt(i + 1));
                
                for (int j = 0; j < preset.length; j++) {
                    if (Math.abs(cand - preset[j]) < Math.abs(cand - preset[min])) {
                        min = j;
                    }
                }
                s += hex[min];
            }
            
            return s;
        }
        
        private int toInt(char c) {
            int rt = 0;
            if (Character.isDigit(c)) {
                rt = c - '0';
            }else {
                rt = 10 + (c - 'a'); 
            }
            
            return rt;
        }
    }
    

    Solution #2: https://leetcode.com/problems/similar-rgb-color/discuss/119844/Concise-java-solution