Google Interview - Summary Part 1


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

4. Guess Word 高频 12次

LC 题目:LC843 猜词,一个未知target,猜一个词会返回正确猜对的字母数

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

当一个单词和其他单词match number为0的次数越多,那么这个单词越不好,因为match number为0时我们减少搜索空间的速度最慢。

假如现在有无限多长度为6的单词,对于word X,和他match number为0的单词有25^6这么多个,然而和X match number为1的单词则减少到了25^5 * 6这么多个,为2时为 C(6, 2) * 25^4,以此类推,match number越大我们下一轮的搜索空间会越小,所以这里我们每一轮都挑选出当前搜索空间中和其他单词match number为0的次数最少的单词作为guess word来猜,这样minimize了每次猜词的worse case。

参考代码:
(Provider: leetcode: lee215)
Time Complexity: O(n ^ 2)
Space Complexity: O(n ^ 2);
class Solution {
   public void findSecretWord(String[] wordlist, Master master) {
       List<String> list = new ArrayList<>();
       for(String str: wordlist) list.add(str);
       for(int i = 0 ; i < 10 ; i++) {
           Map<String, Integer> zeroMatch = new HashMap<>();
           for(String s1: list) {
               zeroMatch.putIfAbsent(s1, 0);
               for(String s2: list) {
                   if(match(s1, s2) == 0) {
                       zeroMatch.put(s1, zeroMatch.get(s1) + 1);
                   }
               }
           }
           Pair pair = new Pair("", 101);  // list size is 100
           for(String key : zeroMatch.keySet()) {
               if(zeroMatch.get(key) < pair.freq) {
                   pair = new Pair(key, zeroMatch.get(key));
               }
           }
           int matchNum = master.guess(pair.key);
           if(matchNum == 6) return;
           List<String> tmp = new ArrayList<>();
           for(String s: list) {
               if(match(s, pair.key) == matchNum) {
                   tmp.add(s);
               }
           }
           list = tmp;
       }
   }
   private static class Pair {
       String key;
       int freq;
       public Pair(String key, int freq) {
           this.key = key;
           this.freq = freq;
       }
   }
   private int match(String s1, String s2) {
       int res = 0;
       for(int i = 0 ; i < s1.length() ; i++) {
           if(s1.charAt(i) == s2.charAt(i)) res++;
       }
       return res;
   }
}


5. LC890 word pattern match 高频8次

题目描述:
给一个word list和一个pattern,返回list中所有和pattern相match的单词
此处的match为能在pattern和word之间找到一个双射函数,和LC Isomorphic String中的双射函数一样

思路:
1. 用两个map,用putIfAbsent存互相的对应关系,然后再查一遍对应
2. 单map把string转换成pattern array,用map.put(char, map.size())存不存在的char
这道题目本质是LC205

6. LC489 位置地形扫地机器人 高频 7次

思路:常规DFS
  1. 需要用参数追踪当前机器人朝向
  2. 每次backtracking时候别忘了掉头回正
  3. 用string记录visit过的位置
参考代码:(disscussion 里面看到的代码量少,比较好写的代码)
class Solution {
   // 0: up, 1: right, 2: down , 3: left
   public void cleanRoom(Robot robot) {
       dfs(new HashSet<>(), 0, 0, 0, robot);
   }
   private void dfs(Set<String> visited, int i, int j, int currDir, Robot r) {
       if(visited.contains(i + "," + j)) return;
       visited.add(i + "," + j);
       r.clean();
       for(int k = 0 ; k < 4; k++) {
           if(r.move()) {
               int x = i, y = j;
               switch(currDir) {
                   case 0: x -= 1; // up
                       break;
                   case 1: y += 1; // right
                       break;
                   case 2: x += 1; // down
                       break;
                   case 3: y -= 1; // left
                       break;
               }
               dfs(visited, x, y, currDir, r);
               r.turnRight();
               r.turnRight();
               r.move();
               r.turnRight();
               r.turnRight();
           }
           r.turnRight();
           currDir += 1;
           currDir %= 4;
       }
   }
}

7. LC855 考试找位子,尽量分散坐,人会离开 高频 6次

思路:见leetcode
1.用优先队列:
用优先队列存slot,slot包含左右端点和长度。exclusive好算。注意如果是最左或最右时长度为right - left,若非则为(right - left) / 2,因为如果选择坐边上可以不管端点。seat时候去pq最大slot,中间切开offer两段。leave时候遍历找到左右两段整合

离开时间复杂度 O(n)
坐下时间复杂度 O(logn)
`

1.2 在优先队列外再建一个BST可以把离开的时间优化到logn。离开的时间主要来自于一个线性的遍历,在BST里可以logn找到左右邻居,并且BST有logn时间的query/insert,不会影响坐下的时间复杂度。

2. 用TreeSet
每次坐下时,遍历set找到最大的距离,并且记录位置,离开则直接删除目标数字

离开时间复杂度O(logn)
坐下时间复杂度O(n)

3. C++用Set(BST)和HashMap(Unordered_Map) 可以做到离开和坐下都是O(logn)

8. Key有过期时间的hashmap 高频 6次

题目:
面试官是个安卓组的小姐姐,45分钟,感觉答得一般,求过o 0
Create a map with expiring entries:
Example
12:00:00 - put(10, 25, 5000)
12:00:04 - get(10) -> 25
12:00:06 - get(10) -> null

思路:两个hash map,一个记录key,value pair,一个记录key的过期时间,get的时候检查key是否过期,如果过期了,删除key返回null
Put方法有三个参数,除了key,value还有个duration

Follow up: 采用更主动的策略删除过期的Key

思路;创建后台线程定期清理过期的Key。
用两个map,一个装<key, value>一个装<key, expiredTime>
在get中采用lazy deletion,get的时候检查key是否过期,如果过期的话两个map中都删除key,返回null。put的时候每次都更新key的expiredTime。
后台线程每过一段时间遍历所有key,调用get方法删除过期key。此处为了避免多线程冲突,Map用ConcurrentHashMap实现。

参考代码  (用后台线程主动删除)

Provider: null
class MyMap<K, V> {
Map<K, V> map;
Map<K, Long> time;
private static final int DEFAULT_CAPACITY = 16;
private static final float DEFAULT_LOAD_FACTOR = 0.75f;
private Thread clearThread = new Thread(new Runnable() {
@Override
public void run() {
while(true) {
try {
Thread.sleep(5000);
}catch(Exception e) {
e.printStackTrace();
}
for(K key : map.keySet()) get(key);
}
}
});
public MyMap() {
this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR);
}
public MyMap(int capacity) {
this(capacity, DEFAULT_LOAD_FACTOR);
}
public MyMap(int capacity, float loadFactor) {
map = new ConcurrentHashMap<>(capacity, loadFactor);
time = new ConcurrentHashMap<>(capacity, loadFactor);
clearThread.start();
}
public synchronized V get(K key) {
long now = System.currentTimeMillis();
Long expired = time.get(key);
if(expired == null) return null;
if(Double.compare(now, expired) > 0) {
map.remove(key);
time.remove(key);
return null;
} else {
return map.get(key);
}
}
public V put(K key, V value, long duration) {
long now = System.currentTimeMillis();
long expired = now + duration;
time.put(key, expired);
return map.put(key, value);
}
}

9. 多个不重复的长方形内随机取点【类似LC497?】 高频 6次

onsite最后一轮的面试题。其他轮都没啥发的必要就不发了。题目是这样的 给你一个list的长方形。。每个长方形面积不一样,但是你要取个点,这个点可以是任何长方形里的。但是要你每次取点的概率都是一样的。不会因为长方形大小而不同。
长方形的输入形式:左下坐标和长宽
  • (主要考察加权抽样和merge squares)
思路:把重复的长方形分成不重复的LC 类似题目:小块,然后用prefix sum进行二分查找
请问follow up是啥思路?用什么思路处理重叠的矩阵?以及是否需要考虑三重或者更多重的重叠区域

LC850 Rectangle Area II (如果有重复部分,思路和此题打碎矩形去掉重复部分的思路一样)
LC497 Random Point in Non-overlapping Rectangles (没有重复部分的原题)
LC528 Random Pick with Weight (类似题目)

对于有多个矩形的情况,我们可以考虑先选出一个矩形,再在该矩形内选点
di要求每个点选取的概率相同,那么选取一个矩形的概率就和该矩形的面积成正比
所以我们可以把所有矩形的面积的和sum算出来,然后在rand一个数%sum,再判断落在哪个矩形里
比如说有面积为3, 2, 1, 4的矩形,总和是10,randM = rand() % 10 ,如果randM==0,1,2就选面积为3的矩形,randM == 3,4就选面积为2的矩形,其他的同理
选出了矩形,然后在该矩形内选点即可

10. LC853 car fleet问题 高频 6次

多辆车再单行路上开,给起始地点和车速,不能超车只能位置重合跟着。问最后有几次的重合车次撞线。

思路:
TreeMap
用treeMap<position, time>去存,从接近target的地方往后遍历,local variable存最大撞线时间。若currTime > maxTime,则车次++

Sort
计算每个位置的车到destination的时间,然后根据位置把车排序,从后往前scan排序后的car数组,如果cars[i]的到达时间比cars[i-1]要晚,说明可以合并cars[i-1]和cars[i],同时更新car[i-1]的到达时间
code
class Solution {
   public int carFleet(int target, int[] position, int[] speed) {
       int len = position.length;
       Car[] cars = new Car[len];
       for(int i = 0 ; i < len ; i++) {
           cars[i] = new Car(position[i], speed[i], target);
       }
       Arrays.sort(cars, (a, b) -> a.pos - b.pos);
       int carFleet = len;
       for(int i = len - 1 ; i > 0 ; i--) {
           if(Double.compare(cars[i].time, cars[i - 1].time) >= 0) {
               cars[i - 1].time = cars[i].time;
               carFleet--;
           }
       }
       return carFleet;
   }
   private static class Car {
       int pos;
       int speed;
       double time;
       public Car(int pos, int speed, int target) {
           this.pos = pos;
           this.speed = speed;
           time = (target - pos + 0.0) / speed;
       }
   }
}

11. LC857 雇工人 高频 6次

思路:
根据描述任何一个合法的pay group里面任意两个worker之间 quality1/quality2 = wage1/wage2,转化一下 wage1/quality1 = wage2 / quality2,即所有的工人他们的paid wage和他们的quality的比值都应该是一样的,根据这个性质,我们每一个合法的pay group只能取最大的wage/quality当作所有工人的pay ratio。

假如我们不取最大的,选择的ratio为w1/q1,而且存在一个工人的wagei/qualityi > w1/q1,转换一下很容易得到 wagei > quaility * w1/q1,即表示该工人的最低工资大于了他实际得到的工资,和题意不符合。

所以有了以上性质后,直接根据ratio排序,然后又需要每个group的pay最小,每个group的总工资计算方法(q1+q2+q3+...+qk)* ratio,所以就是需要quality的sum最小,那每次我们加入了一个新的ratio就把quality最大worker踢出group,这样每次group的pay可以保证是新ratio下的最小pay。遍历数组,记录所有ratio中出现的pay最小值即可。

Code
Provider: leetcode solution
class Solution {
   public double mincostToHireWorkers(int[] quality, int[] wage, int K) {
       int len = quality.length;
       Worker[] worker = new Worker[len];
       for(int i = 0 ; i < len ; i++) {
           worker[i] = new Worker(quality[i], wage[i]);
       }
       Arrays.sort(worker, (a, b) -> Double.compare(a.ratio, b.ratio));
       Queue<Worker> pq = new PriorityQueue<>((a, b) -> b.quality - a.quality);
       int sum = 0;
       double min = Double.MAX_VALUE;
       for(int i = 0 ; i < len; i++) {
           if(pq.size() >= K) {
               Worker tmp = pq.poll();
               sum -= tmp.quality;
           }
           pq.offer(worker[i]);
           sum += worker[i].quality;
           if(pq.size() == K) {
               min = Math.min(min, sum * worker[i].ratio);
           }
       }
       return min;
   }
   private static class Worker {
       int quality;
       int wage;
       double ratio;
       public Worker(int quality, int wage) {
           this.quality = quality;
           this.wage = wage;
           ratio = (wage + 0.0) / quality;
       }
   }
}

12. LC750 Corner Rectangle个数 高频 5次

思路:任选两行for for loop,若相对应列(第三个for)都有点,就count++,然后对这两行的count任取两个组合,加到result上

13. LC815 Bus Route 高频 5次

每个公交车有多个站,给一堆公交车,问A到B点最少换乘次数
思路:BFS + mem。map<stop, List<bus>>,然后用Set<bus>存visited bus(不能用stop查重,会很慢)。每次层序遍历poll出的站都是在这个step中所有能走到的站

14. LC659 Split Array into Consecutive Subsequences 高频 6次

判断一个升序含重复元素的array是否能分成多个三个数字以上构成的顺子

思路:
用freq map先过一遍存频率,再建一个map存我们能用到的tail number。再过第二遍的时候,若freq==0 continue;若能接上前面的顺子,就接;不能则新开一个顺子(记住新开时候直接要把连着的两个数字剔除,因为要保证长度为三);都不行则为false。记住最后别忘了更新当前频率

对于每一个element,我们有两种选择
  1. 把它加入之前构造好的顺子中
  2. 用它新开一个顺子
此处用贪心策略,如果1能满足总是先满足1,因为新开顺子可能失败,即使新开顺子成功,当1能满足的时候,将新开顺子加入之前的顺子也能成功,所以能够选择策略1的时候没必要冒风险选择策略2

目标是用策略1或者2消耗掉所有的元素

如果两个策略都无法选择,直接返回false

用另一个map记录已经构造好的顺子中现在需要哪些尾巴,来实现将当前元素加入构造好的顺子中

15. 王位继承 高频 10+次

【update time:10/22/2018】
void birth(String parent, String name) 父亲名字和孩子名字,生个娃
void death(String name) 此人要死
List<String> getOrder() 返回当前的继承顺序,string array/list

讨论得知,每个人的名字是唯一的,继承顺序符合如下规律:
假设王有大皇子二皇子三皇子,大皇子有长子次子三子,那么继承顺序是王->大皇子->大皇子长子->大皇子次子->大皇子三子->二皇子->三皇子
死掉的人不能出现在继承顺序里,但是如果上面例子中大皇子死了,只需把大皇子移除,原始继承顺序保持不变:王->大皇子长子->大皇子次子->大皇子三子->二皇子->三皇子

三个function会被反复调用,实现function细节。
思路:看起来不难的设计题,DFS只查最左枝v

参考代码11
Provider: null
// key: parent, value: children
Map<String, List<String>> tree = new HashMap<>();
Set<String> dead = new HashSet<>();
String root = "king";
{
tree.put("king", new ArrayList<>());
}

public void birth(String parent, String name) {
if(!tree.containsKey(parent)) {
// throw exception
} else {
tree.get(parent).add(name);
tree.put(name, new ArrayList<>());
}
}

public void death(String name) {
dead.add(name);
}
Zelong Qiu: 这个方程只是lazy delete会不会导致dead越存越大?面试官会不会问如果需要实际删除发方法
根据看到的面经,还没有人被遇到过这个问题,如果有人遇到需要实际删除的问题,欢迎提供思路和代码

Provider: Yang Qi
对于动态删,提供一个思路,用一个map记录子节点到父节点的映射,如果当前节点挂掉,把自己的子节点插入的父节点自身对应的位置之后

public List<String> getOrder(){
List<String> res = new ArrayList<>();
dfs(root, res);
return res;
}

private void dfs(String curr, List<String> res) {
if(!dead.contains(curr)) {
res.add(curr);
}
for(String child : tree.get(curr)) {
dfs(child, res);
}
}

16. LC951 Tree Isomorphism Problem 树的同构问题 高频 5次

https://www.geeksforgeeks.org/tree-isomorphism-problem/
951. Flip Equivalent Binary Trees

思路:简单的DFS
参考代码:
public boolean flipEquiv(TreeNode root1, TreeNode root2) {
if(root1 == null) return root2 == null;
if(root2 == null) return root1 == null;
if(root1.val != root2.val) return false;
return (flipEquiv(root1.left, root2.left)&&flipEquiv(root1.right, root2.right)) || (flipEquiv(root1.left,root2. The right) && flipEquiv(root1.right, root2.left));
}

17. N叉树,要求删一些node,返回list of roots 高频 8次

More Detail : 给一个tree有红的node有蓝的node,把红的去掉后剩下一堆零零散散的tree, 返回这些tree的node,只要node,不要children,也就是说把这个node的children设置成null然后加到list里
参数是这个树的root。找到所有的红点然后delete掉,去掉这些红点之后就会把一个tree变成散落的几个tree,然后返回这几个tree的root。直接一个recursive判断一下,如果这个node是红点的话就ignore 掉再去判断这个node的children,如果这个node是蓝点的话,要看这个蓝点的parent是不是个红点,是的话,这个蓝点就是散落的tree中其中一个tree的root。
思路:简单BFS。。不应是dfs?
想问一下这题返回的顺序重要吗?

没想到怎么做,有没有大佬写了code能发一下的?感激不尽
(Provider: fill your name)
  private void dfs(Node root, Node parent, List<Node> res) {
      if (root == null) {
          return;
      }
      if ((parent == null || parent.color == red) && root.color != red) {
          res.add(root);
      }
      for (Node children : root.children) {
          dfs(child, root, res);
      }
  }
public void dfsHelp (Node root, List<Node> res) {
if (root == null) {
return;
}
if (root.isRed) {
for (Node child:root.childrens) {
if (!child.isRed) {
res.add(child);
}
dfsHelp(child, res);
}
} else {
res.add(root);
Iterator<Node> it = root.childrens.iterator();
while (it.hasNext()) {
Node child = it.next();
if (child.isRed) {
root.childrens.remove(child);
}
dfsHelp(child, res);
}
}
}

class TreeNode(object):
  def __init__(self, val, color):
      self.val = val
      self.color = color
      self.children = []

class Solution(object):
  def listOfRoots(self, root):
      if not root: return []

      ans = []

      def dfs(node, parent):
          if not node: return
          if node.color == 'b':
              if parent.color == 'r': ans.append(node.val)
// should check if parent is None
              else: ans.append(-1)//这里加上负一是为什么?

          for child in node.children:
              dfs(child, node)

      dfs(root, None)
      return ans


18. 可乐饮料机 高频 5次

有一系列按钮,每个按钮按下去会得到一定体积范围的可乐。先给定一个目标体积范围,问不限制按按钮次数,能否确定一定能得到目标范围内的可乐?
举例:有三个按钮,按下去得到的范围是[100, 120], [200, 240], [400, 410],
假设目标是[100, 110], 那答案是不能。因为按下一,可能得到120体积的可乐,不在目标范围里。
假设目标是[90, 120],那答案是可以。因为按下一,一定可以得到此范围内的可乐。
假设目标是[300, 360], 那答案是可以,因为按下一再按二,一定可以得到此范围内
假设目标是[310, 360], 那答案是不能,因为按下一再按二,有可能得到300,永远没可能确定得到这个范围内的可乐。
假设目标是[1, 9999999999],那答案是可以。随便按一个都确定满足此范围。
思路:dfs+memorization从0开始暴力解  一开始[0, 0] 通过bfs、dfs往上加直到出界
public static boolean dfs(List<Soda> sodas, int volumeLower, int volumeUpper,
                             int targetLower, int targetUpper, Map<String, Boolean> memo) {
        
       Boolean val = memo.get(volumeLower + "-" + volumeUpper);
       if (val != null) {
           return val;
       }
        
       if (volumeLower >= targetLower && volumeUpper <= targetUpper) {
           return true;
       }
       if (volumeUpper > targetUpper) {
           return false;
       }
        // if (volumeUpper - volumeLower > targetUpper - targetLower) retuurn false;
       for (Soda soda : sodas) {
           if (dfs(sodas, volumeLower + soda.lower, volumeUpper + soda.upper, targetLower, targetUpper, memo)) {//false的子问题会重复计算
               memo.put(volumeLower + "-" + volumeUpper, true);
               return true;
           }
       }
        
       memo.put(volumeLower + "-" + volumeUpper, false);
       return false;
   }
据说这题是binary search?  这个应该bfs,dfs都能做。但是据说还可以用dp,dp怎么做啊。谁能po个解法?
区间DP的做法:(Provider: anonym)
public static boolean coke(List<List<Integer>> buttons, List<Integer> target) {
   int m = target.get(0);
   int n = target.get(1);
   boolean[][] dp = new boolean[m + 1][n + 1];
   
   //Init
   for (int i = 0; i <= m; ++i) {
     for (int j = 0; j <= n; ++j) {
       for (List<Integer> button: buttons) {
         if (i <= button.get(0) && j >= button.get(1)) {
           dp[i][j] = true;
           break;
         }
       }
     }
   }
 
   for (int i = 0; i <= m; ++i) {
     for (int j = 0; j <= n; ++j) {
       for (List<Integer> button: buttons) {
         int preL = i - button.get(0);
         int preR = j - button.get(1);
         if (preL >= 0 && preR >= 0 && dp[preL][preR]) {
           dp[i][j] = true;
          break;
         }
       }
     }
   }
   
   return dp[m][n];
 }
这算是一个多重背包问题。我曾经被面到过一个类似的:给一个调色板由一堆颜色组成,每个颜色有RGB三个分量。问能否调出一个目标颜色

19. 生成随机迷宫,高频5次

左上到右下,怎么设计可玩性
maze generation. 输入是int[][] board, int[] start, int[] dest,返回一个int[][] maze. 这题题意比较复杂。简单来说就是让你随机生成一个迷宫,
条件是:
   (1)你肯定要生成一些墙,这些墙宽度为1,意思就是board[0][0] - board[0][3]可以是墙,s宽度为1, 长度为4。 但是不能生成board[0][0] - board[1][3]这样的厚墙(2*4)
     (2) 要求这个迷宫有且仅有一条路可以从start到达destination, 另外对于那些不是墙的blank cell,也要有可以从start到达它的路径。 也就是说不能有一些孤岛是不能到达的
     (3) 后来大哥给我简化了一点,如果输入board里面
已经有一些墙, 用1表示,但是这个迷宫并不是具有通路的,然后让你根据以上条件,生成迷宫。

思路:直接暴力小人DFS瞎走,每次走两步,避免生成没有墙的空地。
(Provider: Sean)
public class GenerateRandomMaze {
   public int[][] maze(int n) {
       // Assumptions: n = 2 * k + 1, where k > = 0.
       int[][] maze = new int[n][n];
       // initialize the matrix as only (0,0) is corridor,
       // other cells are all walls at the beginning.
       // later we are trying to break the walls to form corridors.
       for (int i = 0; i < n; i++) {
           for (int j = 0; j < n; j++) {
               if (i == 0 && j == 0) {
                   maze[i][j] = 0;
               } else {
                   maze[i][j] = 1;
               }
           }
       }
       generate(maze, 0, 0);
       return maze;
   }
   private void generate(int[][] maze, int x, int y) {
       // get a random shuffle of all the possible directions,
       // and follow the shuffled order to do DFS & backtrack.
       Dir[] dirs = Dir.values();
       shuffle(dirs);
       for (Dir dir: dirs) {
           // advance by two steps.
           int nextX = dir.moveX(x, 2);
           int nextY = dir.moveY(y, 2);
           if (isValidWall(maze, nextX, nextY)) {
               // only if the cell is a wall(meaning we have not visited before),
               // we break the walls through to make it corridors.
               maze[dir.moveX(x, 1)][dir.moveY(y, 1)] = 0;
               maze[nextX][nextY] = 0;
               generate(maze, nextX, nextY);
           }
       }
   }
   // Get a random order of the directions.
   private void shuffle(Dir[] dirs) {
       for (int i = 0; i < dirs.length; i++) {
           int index = (int)(Math.random() * (dirs.length - i));
           Dir tmp = dirs[i];
           dirs[i] = dirs[i + index];
           dirs[i + index] = tmp;
       }
   }
   // check if the position (x,y) is within the maze and it is a wall.
   private boolean isValidWall(int[][] maze, int x, int y) {
       return x >= 0 && x < maze.length && y >= 0 && y < maze[0].length && maze[x][y] ==
           1;
   }
   enum Dir {
       NORTH(-1, 0), SOUTH(1, 0), EAST(0, -1), WEST(0, 1);
       int deltaX;
       int deltaY;
       Dir(int deltaX, int deltaY) {
           this.deltaX = deltaX;
           this.deltaY = deltaY;
       }
       // move certain times of deltax.
       public int moveX(int x, int times) {
           return x + times * deltaX;
       }
       // move certain times of deltaYy.
       public int moveY(int y, int times) {
           return y + times * deltaY;

       }
   }
}

高频 4次

1.下围棋,判断棋盘上点是否被包围 follow up test case 各种形状
请问各种形状是指什么?是不是指棋盘的形状?如果是的话,那么是不是不同点在于不同的形状的边界情况就会不一样?
请问:这一题哪一篇帖子有比较详细的题目内容吗?感谢
请问这道题有谁做出来能po出详细的code吗?感激不尽
应该说的是棋子的各种摆放。手动Unit test言之成理即可。主要是要测各种edge case
思路:dfs,碰到空子返回false 没被围死

2。n层map,每层m个node,node和edge都有值,问第一层到最后的minimum cost
思路:遍历+改node值?dijkstra吧?
什么叫N层map? map是stl里面的map吗?e不改node值也行吧,反正就是DFS每一条dge存在于同层的node之间?为什么可以改node的值?可能的路径,到底了就和min cost比较就完事了?

3。拿纸牌游戏, 纸牌上面有值,比如说 100, 1, -1, 2, 200, 1. 然后两个人轮流拿,直到拿完。 但是每次只能拿从左边数起的前三个,但是如果你要拿第三个,就必须前两个都拿了,你要拿第二个,就必须第一个也拿了,大家都最优策略,问最后第一个人能拿多少分。
思路:dp存当前人比另一个人能多拿的数,从后往前拿,每次看三个[谁能给个解法链接]

这个是一个蛮经典的dp问题,lintcode上也有类似的题目 https://www.lintcode.com/problem/coins-in-a-line-ii/description


4。image以byte[][]储存 如果想中心镜像翻转怎么弄
思路:跟reverse words一个思路,先翻转每行的byte,再翻转自身(字节翻转可用位运算能快
可以详细讲一下这里怎么用位运算吗

5。已知screen的高和宽,给你最小和最大的fontSize,要求给定一个string,将string用尽可能大的fontSize显示在screen里。已知两个API getHeight(int fontSize), getWidth(char c, int fontSize)
,可以得到每个character在不同fontSize下的高和宽。和面试官交流后,确认string可以拆分成几行显示在screen中
思路:先提出暴力解法,然后用二分法优化

Provider:Qiaoqian Lin
def fitScreen(screen_width, sucreen_height, num_chars, font_sizes):
def ok_or_not(width, height, screen_width, screen_height, num_chars):
num_chars_per_line = screen_width // width
num_chars_per_column = screen_height // height
num_chars_can_fit = num_chars_per_line * num_chars_per_column
return num_chars_can_fit >= num_chars

lo, hi = 0, len(font_sizes) - 1
while lo < hi:
mid = (lo + hi + 1) // 2
font_size = font_sizes[mid]
width, height = API(font_size)
size_ok = ok_or_not(width, height, screen_width, screen_height, num_chars)
if not size_ok:
hi = mid -1
else:
lo = mid
return lo
屏幕超大,如何speedup?

6。LC803 打砖块
思路:最好方法从后往前补。先把砖块全都打掉,然后用贴天花板的砖块dfs+mark,然后从后往前一个一个往上加,加同时若碰上周围有mark的砖块就主动dfs,dfs出来的就是这次打掉的砖块

7。LC253 给一堆interval,问最多要定多少间会议室
思路:可以用heap常规做,也可以把开始、结束时间分别升序排序,然后2pointer往后走。复杂度一样,就是更快

9。给一堆intervals和一个时间点,问这个时间点是不是空闲。follow up多call优化时间
思路:做一遍merge intervals再来一遍binary search
问:这个不merge,直接所有的往treeset里扔可以吗?

10。iterator of iterator
LC类似题目:
LC281 zigzag iterator
题目描述
Implement an Iterator of Iterators which traverses through an arbitrary number of iterators. IE, an iterator which iterates over three list iterators in the following way: L1 = a1, a2, a3 L2 = b1, b2, b3 L3 = c1, c2, c3 Then the iterator should process them in this order: a1, b1, c1, a2, b2, c2, a3, b3, c3
原题链接:https://www.1point3acres.com/bbs/thread-293238-1-1.html

思路:BFS 没什么好说的。。。
http://massivealgorithms.blogspot.com/2015/06/zigzag-iterator-techinterview.html
Provider(ccc/ddd)
class ZigZagIterator {
public:
   ZigZagIterator(vector<vector<int>>& v) {
       for (int i = 0; i < v.size(); ++i) {
           if (!v.empty()) {
               its.push_back({v[i].begin(), v[i].end()});
           }
       }
       current = 0;
   }

   bool HasNext() {
       return !its.empty();
   }

   int Next() {
       auto it = its.begin() + (current % its.size());
       int val = *(it->first);
       if (it->first + 1 < it->second) {
           *it = {it->first + 1, it->second};
       } else {
           its.erase(it);
       }
       ++current;
       return val;
   }

private:
   int current;
   vector<pair<vector<int>::iterator, vector<int>::iterator>> its;

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