Monday, August 31, 2015

Notes: from others

Meeting room
facebook
refhttp://www.fgdsb.com/2015/01/30/meeting-rooms/

Given a array of pairs where each pair contains the start and end time of a meeting (as in int),
Determine if a single person can attend all the meetings
For example:
Input array { pair(1,4), pair(4, 5), pair(3,4), pair(2,3) }
Output: false
Follow up:
determine the minimum number of meeting rooms needed to hold all the meetings.
Input array { pair(1, 4), pair(2,3), pair(3,4), pair(4,5) }
Output: 2

Follow up题也可以换一种形式:
Giving lots of intervals [ai, bi], find a point intersect with the most number of intervals
和Insert/Merge Intervals也属于一类题。

按start排序,找overlap
follow up:
#1 把所有interval的开始和结束点提取出来,vector<int> 里进行排序
#2 遇到开始 + 1,结束 - 1
类似于按时间轴进行扫描,在某一个时间点覆盖最多的interval的数量,为最大的需要房间数量

------------------------------------------------------------------
ZigZag iterator
refhttp://www.fgdsb.com/2015/01/30/zigzag-iterator/#more
以下代码可用于k个iterator
class ZigZagIterator() {
    ZigZagIterator(vector<Iterator> &itrs) {
        this->itrs = itrs;
        pointer = 0;
        if (!itrs[pointer].hasNext()) setNextAvailable();
    }  

    void setNextAvailable() {
        int old = pointer;
        while (true) {
            pointer++;
            pointer %= itrs.size();
            if (itrs[pointer].hasNext()) {
                return;    
            }     
            if (pointer == old) {
                pointer = -1;
                return;
            }
        }
    }

    bool hasNext() {
        return pointer == -1;    
    }
    
    int next() {
        int ret = itrs[pointer];
        setNextAvailable();
        return ret;
    }
    
private:
    vector<Iterator> itrs;
    int pointer;
};

------------------------------------------------------------------------------------
Factor Combination
LinkedIn
refhttp://www.fgdsb.com/2015/01/27/factor-combinations/
dfs
void helper(vector<vector<int>> &rt,int n,vector<int> &cur,int start) {
    if (n == 1) {
        vector<int> t = cur;
        rt.push_back(t);    
        return;
    }
    
    for (int i = start; i <= n; i++) {
        if (n % i != 0) continue;
        cur.push_back(i);
        helper(rt,n / i,cur,i);
        cur.pop_back();
    }
}

vector<vector<int>> factorComb(int n) {
    vector<vector<int>> rt;
    vector<int> cur;
    helper(rt,n,cur,2);
    rt.pop_back();
    return rt;
}

GeeksforGeeks: Dynamic Programming | Set 28 (Minimum insertions to form a palindrome)

Minimum insertions to form a palindrome
ref: http://www.geeksforgeeks.org/dynamic-programming-set-28-minimum-insertions-to-form-a-palindrome/
假设有minInsert(int begin, int end), s为string,返回 s[begin : end]所需的最少insertion
如果s[begin] == s[end], minInsert(begin, end) = minInsert(begin + 1, end - 1);
如果s[begin] != s[end], minInsert(begin, end) = min(minInsert(begin + 1, end), minInsert(begin, end - 1)) + 1;

以下是递归解法:
int minInsert(string s, int begin, int end) {
    if (begin == end) return 0;
    if (begin == end - 1) return (s[begin] == s[end])? 0 : 1;
    if (s[begin] == s[end]) {
        return minInsert(s,begin + 1,end - 1);
    }
    return 1 + min(minInsert(s,begin + 1,end),minInsert(s,begin,end - 1));
}

显而易见,有重复的子问题,所以可以用dp来解决
int minInsert(string s) {
    int n = s.length();
    vector<vector<int>> dp(n,vector<int>(n,0));
    for (int gap = 1; gap < n; gap++) {
        for (int begin = 0, end = gap; end < n; begin++,end++) {
            if (s[begin] == s[end]) {
                dp[begin][end] = dp[begin + 1][end - 1];    
            }else {
                dp[begin][end] = min(dp[begin + 1][end],dp[begin][end - 1]) + 1;    
            }
        }
    }
    
    return dp[0][n - 1];
}

Thursday, August 27, 2015

GeeksforGeeks: Segment Tree | Set 1 (Sum of given range), Segment Tree | Set 2 (Range Minimum Query), Binary Indexed Tree

Segment Tree | Set 1 (Sum of given range)
refhttp://www.geeksforgeeks.org/segment-tree-set-1-sum-of-given-range/
1维
void updateHelper(vector<int> &tree,int diff,int i,int start,int end,int index) {
    if (i < start || i > end) return;
    tree[index] += diff;
    if (start != end) {
        int mid = (start + end) / 2;
        updateHelper(tree,diff,i,start,mid,index * 2 + 1); 
        updateHelper(tree,diff,i,mid + 1,end,index * 2 + 2); 
    }
}

void update(vector<int> &nums, vector<int> &tree,int i,int newValue) {
    int diff = newValue - nums[i];
    nums[i] = newValue;
    updateHelper(tree,diff,i,0,nums.size() - 1,0);
}

int query(vector<int> &tree,int targetS, int targetE, int curS, int curE,int index) {
    if (curS >= targetS && curE <= targetE) {
        return tree[index];
    }
    if (curS > targetE || curE < targetS) {
        return 0;
    }
    int mid = (curS + curE) / 2;
    return query(tree,targetS,targetE,curS,mid,index * 2 + 1) + query(tree,targetS,targetE,mid + 1,curE,index * 2 + 2);
}

int query(vector<int> &nums,vector<int> &tree,int start,int end) {
    return query(tree,start,end,0,nums.size() - 1,0);
}

int buildTree(vector<int> &nums,vector<int> &tree,int start,int end,int i) {
    //cout << i << endl;
    if (start == end) {
        tree[i] = nums[start];
        return tree[i];    
    }
    int mid = (start + end) / 2;
    tree[i] = buildTree(nums,tree,start,mid,2 * i + 1)
                + buildTree(nums,tree,mid + 1,end,2 * i + 2);
    return tree[i];
}

void segmentTree(vector<int> &nums) {
    vector<int> tree(1000,0);
    buildTree(nums,tree,0,nums.size() - 1,0);
}

2维
2维的build tree单独搞不出来,最后只能用调用update,O( n^2 * lgn * lgn)
void updateY(vector<vector<int>> &tree,int y1,int cY1,int cY2,int x,int y,int diff) {
    if (y1 > cY2 || y1 < cY1) return;
    tree[x][y] += diff;
    if (cY1 == cY2) return;
    int mid = (cY1 + cY2) / 2;
    updateY(tree,y1,cY1,mid,x,y * 2 + 1,diff);
    updateY(tree,y1,mid + 1,cY2,x,y * 2 + 2,diff);
    
}

void updateX(vector<vector<int>> &tree,int x1,int y1,int cX1,int cY1,int cX2,int cY2,int x,int y,int diff) {
    if (x1 > cX2 || x1 < cX1) return;
    updateY(tree,y1,cY1,cY2,x,y,diff);
    if (cX1 == cX2) return;
    int mid = (cX1 + cX2) / 2;
    updateX(tree,x1,y1,cX1,cY1,mid,cY2,2 * x + 1,y,diff);
    updateX(tree,x1,y1,mid + 1,cY1,cX2,cY2, 2 * x + 2,y,diff);
}


int getYSum(vector<vector<int>> &tree,int y1,int y2,int cY1,int cY2,int x,int y) {
    if (y1 <= cY1 && y2 >= cY2) {
        return tree[x][y];
    }
    if (y1 > cY2 || y2 < cY1) return 0;
    
    int mid = (cY1 + cY2) / 2;
    return getYSum(tree,y1,y2,cY1,mid,x,y * 2 + 1) + getYSum(tree,y1,y2,mid + 1,cY2,x,y * 2 + 2);
}

int getXSum(vector<vector<int>> &tree,int x1,int y1,int x2,int y2,int cX1,int cY1,int cX2,int cY2,int x,int y) {
    if (x1 <= cX1 && x2 >= cX2) {
        return getYSum(tree,y1,y2,cY1,cY2,x,y);
    }
    if (x1 > cX2 || x2 < cX1) return 0;
    
    int mid = (cX1 + cX2) / 2;
    return getXSum(tree,x1,y1,x2,y2,cX1,cY1,mid,cY2,2 * x + 1,y) + getXSum(tree,x1,y1,x2,y2,mid + 1,cY1,cX2,cY2, 2 * x + 2,y);
}

void twoDSegmentTree(vector<vector<int>> &matrix) {
    vector<vector<int>> tree(1000,vector<int>(1000,0));
    int m = matrix.size(),n = matrix[0].size();
    
    // build 2d segment tree
    for (int i = 0; i < m; i++) {
     for (int j = 0; j < n; j++) {
      updateX(tree,i,j,0,0,m - 1,n - 1,0,0,matrix[i][j]);
     }
    }
}
------------------------------------------------------------------------------------
Segment Tree | Set 2 (Range Minimum Query)
refhttp://www.geeksforgeeks.org/segment-tree-set-1-range-minimum-query/

int updateHelper(vector<int> &tree,int newValue,int i,int start,int end,int index) {
    if (i < start || i > end) return INT_MAX;
    if (start == end) {
        tree[index] = newValue;   
        return tree[index];
    }

    int mid = (start + end) / 2;
    tree[index] = min(updateHelper(tree,newValue,i,start,mid,index * 2 + 1),
                    updateHelper(tree,newValue,i,mid + 1,end,index * 2 + 2));
    
    return tree[index];
}

void update(vector<int> &nums, vector<int> &tree,int i,int newValue) {
    nums[i] = newValue;
    updateHelper(tree,newValue,i,0,nums.size() - 1,0);
}

int query(vector<int> &tree,int targetS, int targetE, int curS, int curE,int index) {
    if (curS >= targetS && curE <= targetE) {
        return tree[index];
    }
    if (curS > targetE || curE < targetS) {
        return INT_MAX;
    }
    int mid = (curS + curE) / 2;
    return min(query(tree,targetS,targetE,curS,mid,index * 2 + 1), query(tree,targetS,targetE,mid + 1,curE,index * 2 + 2));
}

int query(vector<int> &nums,vector<int> &tree,int start,int end) {
    return query(tree,start,end,0,nums.size() - 1,0);
}

int buildTree(vector<int> &nums,vector<int> &tree,int start,int end,int i) {
    if (start == end) {
        tree[i] = nums[start]; 
        return tree[i];
    }
    int mid = (start + end) / 2;
    tree[i] = min(buildTree(nums,tree,start,mid,2 * i + 1),
                buildTree(nums,tree,mid + 1,end,2 * i + 2));
    return tree[i];
}

void segmentTree(vector<int> &nums) {
    vector<int> tree(1000,0);
    buildTree(nums,tree,0,nums.size() - 1,0);
}

-----------------------------------------------------------------
Binary Indexed Tree
refhttp://www.geeksforgeeks.org/binary-indexed-tree-or-fenwick-tree-2/
http://www.hawstein.com/posts/binary-indexed-trees.html
http://algorithmsandme.in/2015/02/binary-indexed-trees/
1维
void update(vector<int> &bit,int idx,int diff) {
    while (idx < bit.size()) {
  bit[idx] += diff;
  idx += idx & (-idx);
 }
}

int get(vector<int> &bit,int idx) {
    int sum = 0;
    while (idx > 0) {
        sum += bit[idx];
        idx -= idx & (-idx);
    }
    
    return sum;
}

vector<int> buildTree(vector<int> &nums) {
    vector<int> bit(nums.size() + 1,0);
    for (int i = 0; i < nums.size(); i++) {
        update(bit,i + 1,nums[i]);
    }
    
    return bit;
    
}

void biTree(vector<int> &nums) {
    vector<int> bit = buildTree(nums);
}

2维bit

#1 每个row的sum,再做一个bit,就成了2维的了
求[i][j]的值需要从[0][i] 到 [i][j]

#2 如果求[x1,y1]到[x2,y2]的矩阵的值,则要做一些矩阵减法
void update(vector<vector<int>> &bit, int row,int col,int diff) {
    while (row < bit.size()) {
        int idx = col;
        while (idx < bit[0].size()) {
            bit[row][idx] += diff;
            idx += idx & (-idx);
        }
        row += row & (-row);
    }
}

int read(vector<vector<int>> &bit, int row,int col) {
 int sum = 0;
 while (row > 0) {
  int idx = col;
  while (idx > 0) {
   sum += bit[row][idx];
   idx -= idx & (-idx); 
  }
  row -= row & (-row);
 }
 
 return sum;
}

vector<vector<int>> buildBit(vector<vector<int>> &matrix) {
    vector<vector<int>> bit(matrix.size() + 1,vector<int>(matrix[0].size() + 1,0));
    
    for (int row = 0; row < matrix.size(); row++) {
        for (int col = 0; col < matrix[0].size(); col++) {
            update(bit,row + 1,col + 1,matrix[row][col]);
        }
    }
    return bit;
}

void twoDBit(vector<vector<int> > &matrix) {
    vector<vector<int>> bit = buildBit(matrix);
    
}

Wednesday, August 26, 2015

Google interview questions #7

ref: 讨论 http://www.mitbbs.com/article_t1/JobHunting/32574909_0_1.html
13年11月,国内电面

10月17日,第一轮电面:
第一题:上海的电话isTree(vector<pair<int,int> >& edges); (离散化+dfs判环
判联通)
树的条件:
#1 没有环
#2 所有node都联通
dfs + hashmap记录visit情况

并交集
http://blog.csdn.net/dm_vincent/article/details/7655764
class UnionFind {
public:
    UnionFind(int number) {
        count = number;
        for (int i = 0; i < number; i++) {
            parent.push_back(i);
            size.push_back(1);
        }
    }
    
    int find(int x) {
        while (x != parent[x]) {
            x = parent[x];
        }
        return x;
    }
    
    void do_union(int x,int y) {
        int p1 = find(x);
        int p2 = find(y);
        if (x == y) return;
        if (size[p1] > size[p2]) {
            size[p1] += size[p2];
            parent[p2] = p1;
        }else {
            size[p2] += size[p1];
            parent[p1] = p2;
        }
        count--;
    }
    
    bool hasCycle() {
        return count == 1;    
    }
    
private:
    int count;
    vector<int> parent;
    vector<int> size;
};

bool isTree(vector<pair<int,int>> &edges, int n) {
    UnionFind uf(n);
    for (int i = 0; i < edges.size(); i++) {
        if (uf.find(edges[i].first) == uf.find(edges[i].second)) {
            return false;    
        }
        uf.do_union(edges[i].first,edges[i].second);
    }
    
    return uf.hasCycle();
}

第二题,
Given a 2D space of maximum size NxN which supports two operations :
[1] void UPDATE(x,y,v) - sets the value of cell [x,y] to v
[2] int QUERY(x1,y1,x2,y2) - returns sub-rectangle sum (x1,y1) to (x2,y2)
inclusive, and there is an infinite stream of such 2 types of
operations which have to supported. How would you store the values for
efficient updates and retrievals ? (二维线段树 说算法+分析复杂度)
一维线段树:
http://www.cnblogs.com/TenosDoIt/p/3453089.html
http://www.geeksforgeeks.org/segment-tree-set-1-sum-of-given-range/
http://www.geeksforgeeks.org/segment-tree-set-1-range-minimum-query/

二维线段树:



第一轮答得还可以。
10月30日,第二轮电面:(挂)
美国的电话,面试官很nice:
第一题。一个二叉树,节点值有正有负,求树中的任意路径的最大值。路径的值就
是路径经过点的值的和。然后我说dfs,面试官就让写代码 。 写代码一开始dfs的接
口声明有问题,期间停下来修改了一下,然后写完。被面试官查出1个bug。面试官提示
了,一开始找出了另外个bug;面试官又提示了一下,才找出了面试官想要我fix的bug
。杯具。

LC # 124

第二题。给三个字符串,a,b,c。问a 和b 能不能组成c,且保证c 中a b 的字母
顺序不变。 一开始我给了一个没验证贪心的想法。然后面试官让我验证或举个反例。
我想贪心多数没戏,就又说了种dp的思路。面试官让我写下来。我写完之后,让我解释
了解释。然后突然悲催地发现我的解法是O(2^n)的。。面试后想想如果我的解法状态去重后,就和普通的dp无异了。。 杯具 。。 然后就挂了。
假设:a.length + b.length = c.length, a和b中有相同字符

3个指针 ia, ib, ic分别指向a, b, c. foo() : boolean 返回a, b能否组成c
bool foo(ia,ib,ic) {
    bool flag1 = false;
    bool flag2 = false;
    if (a[ia] == c[ic]) {
        flag1 = foo(ia + 1, ib, ic + 1);
    }
    if (b[ib] == c[ic]) {
        flag1 = foo(ia, ib + 1, ic + 1);
    }
    return flag1 || flagb
}

显而易见,子问题重复,所以用DP
bool canBuild(string a,string b,string c) {
    if (a.length() + b.length() != c.length()) return false;
    int m = a.length(), n = b.length();
    vector<vector<bool>> dp(m + 1,vector<bool>(n + 1,false));
    dp[0][0] = true;
    // pre-process
    for (int i = 0; i < m; i++) {
        if (a[i] == c[i]) {
            dp[i + 1][0] = true;
        }else {
            break;
        }
    }
    // pre-process
    for (int i = 0; i < n; i++) {
        if (b[i] == c[i]) {
            dp[0][i + 1] = true;
        }else {
            break;    
        }
    }
    
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            dp[i + 1][j + 1] = (a[i] == c[i + j + 1] && dp[i][j + 1])
                    || (b[j] == c[i + j + 1] && dp[i + 1][j]);
        }
    }
    
    return dp[m][n];
}

--------------------------------------------------------------------------------------------------------
ref: https://vermashubhang.wordpress.com/2014/02/28/google-summer-internship-interview-questions/
1. You are given a number in the formed of a linked list as given below :

eg. 1 -> 2 -> 3 -> 4 represents the number 1234

You have to increment the number by 1 i.e. you have to change the number in the linked list to 1235. The number in the list can be arbitrarily large.

Take two pointers to mark the last non-nine digit and the second one for traversal of the array

2. What is a Binary Search Tree ? Given a binary Search Tree and a value as N. You have to find out the number in the BST nearest to this number N i.e. with the minimum modulus of difference value.

lgN,小的走左边,大的右边,每次记录difference

3. You are given a Binary Search Tree and a sum value S. You have to find out the pair of numbers in the binary search Tree whose sum is equal to S .

hashmap, 走一遍tree
two pointer???怎么做

4. You are given an array of numbers

a1 , a2, a3, a4, a5,…….

you have to sort the array in the following form.

a1 <=a2 >= a3 <= a4 >= a5.

扫一遍,不符合rule的就swap

void reorder(vector<int> &nums) {
    if (nums.size() < 2) {
        return;
    }
    
    for (int i = 0; i < nums.size() - 1; i++) {
        if (i % 2 == 0 && nums[i] > nums[i + 1]) {
            swap(nums[i],nums[i + 1]);
        }
        if (i % 2 == 1 && nums[i] < nums[i + 1]) {
            swap(nums[i],nums[i + 1]);
        }
    }
}
----------------------------------------------
ref: http://www.mitbbs.com/article_t/JobHunting/33054861.html

给一个 n*m 的房间,房间里存在各种可能的墙,房间的格子里已经放了 e 个器材,要
求新放一个器材,放置位置距其它 e 个器材的距离最近。Breadth-first search.

从每个器材处出发做bfs,各个器材所生成的距离累加。最后取最小值
O(e * m * n)

如果题目是不包含障碍物:
#1 各建1个n长度和m长度的数组,n[i]表示所有row index小于i的器材的个数,m[i]表示所有col index小于i的器材个数
o(n * m)
#2 根据m[i]算出第一行的值
#3 如果index横向移动,只需要m[i]来计算,如果纵向移动,需要n[i]

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


在别处看到别的公司也考,突然想起来我G onsite貌似挂在这题上了。想请教请教各位
大牛怎么做

“给你一棵树,不是binary的,每个节点会有任意个children,然后这棵树是存在一个
数组里的,数组的每个元素就是一个节点,节点包含了它的index以及它的parent的
index,而不是children的index哦,所以这棵树是从child指向parent的。最后是给我
这个数组和一个节点的index,让我删除这个index以及它的子树,只能用O(n)的空间复
杂度,而且大小是确定好的”
数组里各个node是打乱的,不是topologically sorted的

update:
举个例子:
[3,1,4,1,5,7,2,6]
删index 1
得到
[x,x,4,x,5,7,2,6] (x代表被删除)
最终输出
[1,2,4,0,3]

删除操作:用hashmap,用一个记录走过的node。用一个array记录node往上走的路径,碰到为已删除或者是要删除的,就删除当前array里所有node。
空间跟时间都为O(n)

重新排序:开一个额外array来记录node之前跟之后的index对应

例子,删除操作后:
index:             0 1 2 3 4 5 6 7
parent Index:  x 5 4 x 1 n x x
需要返回:      1 n 3 0


-------------------------------------------------------------
ref: http://www.mitbbs.com/article_t/JobHunting/33060313.html

给一个m*n的矩阵,每个点不是0就是1,所有值为1的点是连通的,给你一个点的坐标,
告诉你这个点的值是1,求一个最小的矩形,能把所有的1包括在内
同学给了一个n logm的算法,但是面试官并不满意,想问问各位还有更优的算法吗?

寻找边界:从给定的点向四边做2分扫描,对每一行或每一列再线性扫。复杂度为O(m * lg n)或者O(m * lg k)

 -----------------------------------------------------------------
ref: http://www.mitbbs.com/article_t/JobHunting/33061095.html

没有一轮国人,过程感觉也没有很亲切,看来还是要中国人多才好。九月初的onsite,
一共五轮,四轮coding一轮系统设计(第一轮)
1. billion级别的raw data,怎样村在多个节点中,实现有效率的查找。给定条件是数
据是已经在那里的,而且不会被修改。
2. valid bst讨论属性,边界条件
3. 给一个排序的数组, 1 2 5 8 9 11 16,输出missing range比如3-4,6-7,10,
12-15
4. iterator of iterator,写一个iterator iterate所有的元素,例如
itr1 1 2 3 4
itr2 5 6 7 8
itr3 9 10 11 12
写一个iterator输出1 5 9 2 6 10 ...
5. 类似moving average,固定size不断update average,讨论多县城的情况。

Tuesday, August 25, 2015

Day 121, #264, #263, #242, #257, #258, #268, #260 Ugly Number II, Ugly Number, Valid Anagram, Binary Tree Paths, Add Digits, Missing Number, Single Number III

Ugly Number II  
Write a program to find the n-th ugly number.
Ugly numbers are positive numbers whose prime factors only include 2, 3, 5. For example, 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 is the sequence of the first 10 ugly numbers.
Note that 1 is typically treated as an ugly number.
Hint:
  1. The naive approach is to call isUgly for every number until you reach the nth one. Most numbers are not ugly. Try to focus your effort on generating only the ugly ones.
  2. An ugly number must be multiplied by either 2, 3, or 5 from a smaller ugly number.
  3. The key is how to maintain the order of the ugly numbers. Try a similar approach of merging from three sorted lists: L1, L2, and L3.
  4. Assume you have Uk, the kth ugly number. Then Uk+1 must be Min(L1 * 2, L2 * 3, L3 * 5).
----------------------------------------------------
ref: http://www.geeksforgeeks.org/ugly-numbers/
COME_BACK
1 * 2, 2 * 2, 3 * 2, 4 * 2, 5 * 2, 6 * 2, 8 * 2...
1 * 3, 2 * 3, 3 * 3, 4 * 3, 5 * 3, 6 * 3, 8 * 3...
1 * 5, 2 * 5, 3 * 5, 4 * 5, 5 * 5, 6 * 5, 8 * 5...
这题要点在把上面3个list排序,而且上面的序号也是根据ugly number来增加,并不是每次都+ 1,所以要用一个vector来记录出现过的ugly number
p2, p3, p5分别指向3个list

class Solution {
public:
    int nthUglyNumber(int n) {
        vector<int> ugly(n);
        ugly[0] = 1;
        int p2 = 0, p3 = 0, p5 = 0;
        
        for (int i = 1; i < n; i++) {
            int nextUgly = min(ugly[p2] * 2,min(ugly[p3] * 3,ugly[p5] * 5));
            
            if (nextUgly == ugly[p2] * 2) {
                p2++;
            }
            if (nextUgly == ugly[p3] * 3) {
                p3++;
            }
            if (nextUgly == ugly[p5] * 5) {
                p5++;
            }
            ugly[i] = nextUgly;
        }
        
        return ugly[n - 1];
    }
};

Ugly Number
Write a program to check whether a given number is an ugly number.
Ugly numbers are positive numbers whose prime factors only include 2, 3, 5. For example, 6, 8 are ugly while 14 is not ugly since it includes another prime factor 7.
Note that 1 is typically treated as an ugly number.
------------------------------------------------
class Solution {
public:
    bool isUgly(int num) {
        if (num == 1) return true;
        while (true) {
            int t = num;
            if (num % 2 == 0) {
                num /= 2;
            }
            if (num % 3 == 0) {
                num /= 3;
            }
            if (num % 5 == 0) {
                num /= 5;
            }
            if (num == t) return false;
            if (num == 1) return true;
        }
    }
};

Valid Anagram
Given two strings s and t, write a function to determine if t is an anagram of s.
For example,
s = "anagram", t = "nagaram", return true.
s = "rat", t = "car", return false.
Note:
You may assume the string contains only lowercase alphabets.
--------------------------------------------------------------

class Solution {
public:
    bool isAnagram(string s, string t) {
        if (s.length() != t.length()) return false;
        vector<int> dp(256,0);
        for (int i = 0; i < s.length(); i++) {
            dp[s[i]]++;
        }
        
        for (int i = 0; i < t.length(); i++) {
            if (dp[t[i]] == 0) return false;
            dp[t[i]]--;
        }
        
        return true;
    }
};

Binary Tree Paths
Given a binary tree, return all root-to-leaf paths.
For example, given the following binary tree:
   1
 /   \
2     3
 \
  5
All root-to-leaf paths are:
["1->2->5", "1->3"]
-------------------------------------------------------

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    void helper(vector<string> &rt, TreeNode *root, string path) {
        if (root->left == NULL && root->right == NULL) {
            rt.push_back(path + to_string(root->val));
        }
        if (root->left != NULL) {
            helper(rt,root->left,path + to_string(root->val) + "->");
        }
        if (root->right != NULL) {
            helper(rt,root->right,path + to_string(root->val) + "->");
        }
    }

    vector<string> binaryTreePaths(TreeNode* root) {
        vector<string> rt;
        if (root == NULL) return rt;
        
        helper(rt,root,"");
        return rt;
    }
};

Add Digits
Given a non-negative integer num, repeatedly add all its digits until the result has only one digit.
For example:
Given num = 38, the process is like: 3 + 8 = 111 + 1 = 2. Since 2 has only one digit, return it.
Follow up:
Could you do it without any loop/recursion in O(1) runtime?
Hint:
  1. A naive implementation of the above process is trivial. Could you come up with other methods?
  2. What are all the possible results?
  3. How do they occur, periodically or randomly?
  4. You may find this Wikipedia article useful.
--------------------------------------------------------
class Solution {
public:
    int addDigits(int num) {
        if (num == 0) return 0;
        return num - (num - 1) / 9 * 9;
    }
};

Missing Number
Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find the one that is missing from the array.
For example,
Given nums = [0, 1, 3] return 2.
Note:
Your algorithm should run in linear runtime complexity. Could you implement it using only constant extra space complexity?
---------------------------------------------------------
类似first missing positive
class Solution {
public:
    int missingNumber(vector<int>& nums) {
        for (int i = 0; i < nums.size(); i++) {
            int target = nums[i];
            while (target >= 0 && target < nums.size() && nums[target] != target) {
                swap(nums[i],nums[target]);
                target = nums[i];
            }
        }
        
        for (int i = 0; i < nums.size(); i++) {
            if (i != nums[i]) return i;
        }
        return nums.size();
    }
};

Single Number III
Given an array of numbers nums, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once.
For example:
Given nums = [1, 2, 1, 3, 2, 5], return [3, 5].
Note:
  1. The order of the result is not important. So in the above example, [5, 3] is also correct.
  2. Your algorithm should run in linear runtime complexity. Could you implement it using only constant space complexity?
---------------------------------------------------------------
ref:https://leetcode.com/discuss/52351/accepted-java-space-easy-solution-with-detail-explanations
一路xor下来,最后结果肯定是2个不同数的xor结果,所以2进制上肯定包含1
任意取一位1,根据此1将array里的数划分为2半,每一半各包含一个只出现一次的数
class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) {
        vector<int> rt(2,0);
        int xorNum = 0;
        for (int i = 0; i < nums.size(); i++) {
            xorNum ^= nums[i];
        }
        xorNum &= -xorNum;
        for (int i = 0; i < nums.size(); i++) {
            if ((xorNum & nums[i]) == 0) {
                rt[0] ^= nums[i];
            }else {
                rt[1] ^= nums[i];
            }
        }
        
        return rt;
    }
};

Thursday, August 20, 2015

Day 120, Longest Increasing Subsequence, Longest Common Substring Show result, Longest Increasing Continuous subsequence II

Longest Increasing Subsequence


Given a sequence of integers, find the longest increasing subsequence (LIS).
You code should return the length of the LIS.
Have you met this question in a real interview?
Yes
Example
For [5, 4, 1, 2, 3], the LIS  is [1, 2, 3], return 3
For [4, 2, 4, 5, 3, 7], the LIS is [4, 4, 5, 7], return 4
Challenge
Time complexity O(n^2) or O(nlogn)
Clarification
What's the definition of longest increasing subsequence?
    * The longest increasing subsequence problem is to find a subsequence of a given sequence in which the subsequence's elements are in sorted order, lowest to highest, and in which the subsequence is as long as possible. This subsequence is not necessarily contiguous, or unique.  
    * https://en.wikipedia.org/wiki/Longest_common_subsequence_problem
---------------------------------------------------------------------
O(n^2)
class Solution {
public:
    /**
     * @param nums: The integer array
     * @return: The length of LIS (longest increasing subsequence)
     */
    int longestIncreasingSubsequence(vector<int> nums) {
        // write your code here
        if (nums.size() == 0) return 0;
        vector<int> dp(nums.size(),1);
        int longest = 0;
        for (int i = 0; i < nums.size(); i++) {
            for (int j = 0; j < i; j++) {
                if (nums[j] <= nums[i]) {
                    dp[i] = max(dp[i],dp[j] + 1);
                }
                longest = max(longest,dp[i]);
            }
        }
        
        return longest;
    }
};

geeksforgeeks,O(n lg n)

Longest Common Substring Show result 
Given two strings, find the longest common substring.
Return the length of it.
Have you met this question in a real interview? 
Yes
Example
Given A = "ABCD", B = "CBCE", return 2.
Note
The characters in substring should occur continuously in original string. This is different with subsequence.

Challenge
O(n x m) time and memory.
---------------------------------------------------
画个2d矩阵就明白了
class Solution {
public:    
    /**
     * @param A, B: Two string.
     * @return: the length of the longest common substring.
     */
    int longestCommonSubstring(string &A, string &B) {
        // write your code here
        int m = A.length(), n = B.length();
        vector<vector<int> > dp(m + 1,vector<int>(n + 1,0));
        int longest = 0;
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (A[i - 1] == B[j - 1]) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                    longest = max(longest,dp[i][j]);
                }
            }
        }
        
        return longest;
    }
};

线性额外空间
class Solution {
public:    
    /**
     * @param A, B: Two string.
     * @return: the length of the longest common substring.
     */
    int longestCommonSubstring(string &A, string &B) {
        // write your code here
        int m = A.length(), n = B.length();
        vector<int> dp(n + 1,0);
        int longest = 0;
        for (int i = 1; i <= m; i++) {
            for (int j = n; j >= 1; j--) {
                if (A[i - 1] == B[j - 1]) {
                    dp[j] = dp[j - 1] + 1;
                    longest = max(longest,dp[j]);
                }else {
                    dp[j] = 0;
                }
            }
        }
        
        return longest;
    }
};

Longest Increasing Continuous subsequence II
Give you an integer matrix (with row size n, column size m),find the longest increasing continuous subsequence in this matrix. (The definition of the longest increasing continuous subsequence here can start at any row or column and go up/down/right/left any direction).
Have you met this question in a real interview? 
Yes
Example
Given a matrix:
[
  [1 ,2 ,3 ,4 ,5],
  [16,17,24,23,6],
  [15,18,25,22,7],
  [14,19,20,21,8],
  [13,12,11,10,9]
]
return 25

Challenge
O(nm) time and memory.
--------------------------------------------------
以每一点为path的起始,它所得到最长递增数列都是恒定的
所以用memoization即可
class Solution {
public:
    /**
     * @param A an integer matrix
     * @return  an integer
     */
    int dfs(vector<vector<int>>& A,vector<vector<int>> &dp,int row,int col) {
        if (dp[row][col] != 0) return dp[row][col];

        if (row + 1 < A.size() && A[row + 1][col] > A[row][col]) {
            dp[row][col] = max(dp[row][col],dfs(A,dp,row + 1,col));
        }
        if (row - 1 >= 0 && A[row - 1][col] > A[row][col]) {
            dp[row][col] = max(dp[row][col],dfs(A,dp,row - 1,col));
        }
        if (col - 1 >= 0 && A[row][col - 1] > A[row][col]) {
            dp[row][col] = max(dp[row][col],dfs(A,dp,row,col - 1));
        }
        if (col + 1 < A[0].size() && A[row][col + 1] > A[row][col]) {
            dp[row][col] = max(dp[row][col],dfs(A,dp,row,col + 1));
        }
        
        dp[row][col]++;
        return dp[row][col];
    }
     
    int longestIncreasingContinuousSubsequenceII(vector<vector<int>>& A) {
        // Write your code here
        if (A.size() == 0) return 0;
        int m = A.size(), n = A[0].size();
        vector<vector<int>> dp(m,vector<int>(n,0));
        int longest = 0;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (dp[i][j] == 0) {
                    dp[i][j] = dfs(A,dp,i,j);
                }
                longest = max(longest,dp[i][j]);
            }
        }
        
        return longest;
    }
};

遍历,所有点按高度排序
struct Dot {
        int row;
        int col;
        int height;
        Dot(int x,int y,int h):row(x),col(y),height(h) {
        }
    };

class Solution {
public:
    static bool cmp(const Dot &d1,const Dot &d2) {
        return d1.height < d2.height;
    }

    /**
     * @param A an integer matrix
     * @return  an integer
     */
    int longestIncreasingContinuousSubsequenceII(vector<vector<int>>& A) {
        // Write your code here
        if (A.size() == 0) return 0;
        int m = A.size(), n = A[0].size();
        vector<vector<int>> len(m,vector<int>(n,0));
        vector<Dot> dots;
        
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                Dot d(i,j,A[i][j]);
                dots.push_back(d);
            }
        }
        
        sort(dots.begin(),dots.end(),cmp);
        int longest = 0;
        for (int i = 0; i < dots.size(); i++) {
            if (dots[i].row + 1 < m && A[dots[i].row + 1][dots[i].col] > dots[i].height
                && len[dots[i].row + 1][dots[i].col] < len[dots[i].row][dots[i].col] + 1) {
                len[dots[i].row + 1][dots[i].col] = len[dots[i].row][dots[i].col] + 1;
            }
            
            if (dots[i].col + 1 < n && A[dots[i].row][dots[i].col + 1] > dots[i].height
                && len[dots[i].row][dots[i].col + 1] < len[dots[i].row][dots[i].col] + 1) {
                len[dots[i].row][dots[i].col + 1] = len[dots[i].row][dots[i].col] + 1;
            }
            
            if (dots[i].row - 1 >= 0 && A[dots[i].row - 1][dots[i].col] > dots[i].height
                && len[dots[i].row - 1][dots[i].col] < len[dots[i].row][dots[i].col] + 1) {
                len[dots[i].row - 1][dots[i].col] = len[dots[i].row][dots[i].col] + 1;
            }
            
            if (dots[i].col - 1 >= 0 && A[dots[i].row][dots[i].col - 1] > dots[i].height
                && len[dots[i].row][dots[i].col - 1] < len[dots[i].row][dots[i].col] + 1) {
                len[dots[i].row][dots[i].col - 1] = len[dots[i].row][dots[i].col] + 1;
            }
        }
        
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                longest = max(longest,len[i][j]);
            }
        }
        
        return longest + 1;
    }
};

Thursday, August 13, 2015

Day 119, #239,237,238,240 Sliding Window Maximum, Delete Node in a Linked List, Product of Array Except Self, Different Ways to Add Parentheses

Sliding Window Maximum 
Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position.
For example,
Given nums = [1,3,-1,-3,5,3,6,7], and k = 3.
Window position                Max
---------------               -----
[1  3  -1] -3  5  3  6  7       3
 1 [3  -1  -3] 5  3  6  7       3
 1  3 [-1  -3  5] 3  6  7       5
 1  3  -1 [-3  5  3] 6  7       5
 1  3  -1  -3 [5  3  6] 7       6
 1  3  -1  -3  5 [3  6  7]      7
Therefore, return the max sliding window as [3,3,5,5,6,7].
Note: 
You may assume k is always valid, ie: 1 ≤ k ≤ input array's size for non-empty array.
Follow up:
Could you solve it in linear time?
Hint:
  1. How about using a data structure such as deque (double-ended queue)?
  2. The queue size need not be the same as the window’s size.
  3. Remove redundant elements and the queue should store only elements that need to be considered.
--------------------------------------------------------------------------------
http://articles.leetcode.com/2011/01/sliding-window-maximum.html
compare function的写法跟用法
O(NlgN)
class Cmp{
public:
    bool operator() (pair<int,int> &p1,pair<int,int> &p2) {
        return p1.second < p2.second;
    }  
};

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        if (k == 0) {
            vector<int> rt;
            return rt;
        }
        if (k == 1) return nums;
        vector<int> rt(nums.size() - k + 1);
        priority_queue<pair<int,int>,vector<pair<int,int>>,Cmp> heap; // index, value
        for (int i = 0; i < k - 1; i++) {
            heap.push(make_pair(i,nums[i]));
        }
        
        for (int i = k - 1; i < nums.size(); i++) {
            heap.push(make_pair(i,nums[i]));
            while (heap.top().first < i - k + 1) {
                heap.pop();
            }
            rt[i - k + 1] = heap.top().second;
        }
        
        return rt;
    }
};

O(n)
class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        vector<int> rt;
        deque<int> que;
        for (int i = 0; i < k - 1; i++) {
            while (!que.empty() && nums[i] >= nums[que.back()]) {
                que.pop_back();
            }
            que.push_back(i);
        }
        
        for (int i = k - 1; i < nums.size(); i++) {
            while (!que.empty() && nums[i] >= nums[que.back()]) {
                que.pop_back();
            }
            if (!que.empty() && que.front() < i - k + 1) {
                que.pop_front();
            }
            que.push_back(i);
            rt.push_back(nums[que.front()]);
        }
        
        return rt;
    }
};

Java
public class Solution {
    
    public int[] maxSlidingWindow(int[] nums, int k) {
        if (nums == null || nums.length == 0 || k <= 0) return new int[0];
        
        int rt[] = new int[nums.length - k + 1];
        Deque<Integer> q = new ArrayDeque<>();
        
        for (int i = 0; i < nums.length; i++) {
            if (!q.isEmpty() && q.getFirst() <= i - k) {
                q.removeFirst();
            }
            
            while (!q.isEmpty() && nums[q.getLast()] < nums[i]) {
                q.removeLast();
            }
            
            q.addLast(i);
            if (i >= k - 1) {
                rt[i - k + 1] = nums[q.getFirst()];
            }
        }
        
        return rt;
    }
}
另一种思路,Deque里的值是递增
class Solution {
    
    public int[] maxSlidingWindow(int[] nums, int k) {
        int n = nums.length;
        if (n == 0) return new int[0];
        
        int[] rt = new int[n - k + 1];
        Deque<Integer> deq = new LinkedList<>();
        
        for (int i = 0; i < n; i++) {
            while (!deq.isEmpty() && deq.peekLast() <= i - k) {
                deq.pollLast();
            }
            
            if (deq.isEmpty() || nums[deq.peekLast()] <= nums[i]) deq.addLast(i);
            else {
                while (!deq.isEmpty() && nums[deq.peekFirst()] <= nums[i]) {
                    deq.pollFirst();
                }
                deq.addFirst(i);
            }
            
            if (i >= k - 1) rt[i - k + 1] = nums[deq.peekLast()];
        }
        
        return rt;
    }
}

Delete Node in a Linked List
Write a function to delete a node (except the tail) in a singly linked list, given only access to that node.
Supposed the linked list is 1 -> 2 -> 3 -> 4 and you are given the third node with value 3, the linked list should become 1 -> 2 -> 4 after calling your function.
-----------------------------------------------

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    void deleteNode(ListNode* node) {
        node->val = node->next->val;
        node->next = node->next->next;
    }
};

Product of Array Except Self
Given an array of n integers where n > 1, nums, return an array output such that output[i] is equal to the product of all the elements of nums except nums[i].
Solve it without division and in O(n).
For example, given [1,2,3,4], return [24,12,8,6].
Follow up:
Could you solve it with constant space complexity? (Note: The output array does not count as extra space for the purpose of space complexity analysis.)

-----------------------------------------------------------------
O(n) extra space
class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        vector<int> left(nums.size(),1);
        vector<int> right(nums.size(),1);
        vector<int> rt(nums.size());
        for (int i = 1; i < nums.size(); i++) {
            left[i] = nums[i - 1] * left[i - 1];
        }
        for (int i = nums.size() - 2; i >= 0; i--) {
            right[i] = nums[i + 1] * right[i + 1];
        }
        
        for (int i = 0; i < nums.size(); i++) {
            rt[i] = left[i] * right[i];
        }
        
        return rt;
    }
};

constant space, output array doesn't count as extra space
class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        vector<int> left(nums.size(),1);
        for (int i = 1; i < nums.size(); i++) {
            left[i] = nums[i - 1] * left[i - 1];
        }
        
        int right = 1;
        for (int i = nums.size() - 1; i >= 0; i--) {
            left[i] = right * left[i];
            right *= nums[i];
        }
        
        return left;
    }
};

Different Ways to Add Parentheses
Given a string of numbers and operators, return all possible results from computing all the different possible ways to group numbers and operators. The valid operators are+- and *.

Example 1
Input: "2-1-1".
((2-1)-1) = 0
(2-(1-1)) = 2
Output: [0, 2]

Example 2
Input: "2*3-4*5"
(2*(3-(4*5))) = -34
((2*3)-(4*5)) = -14
((2*(3-4))*5) = -10
(2*((3-4)*5)) = -10
(((2*3)-4)*5) = 10
Output: [-34, -14, -10, -10, 10]
------------------------------------------------------
Catalan number, divide and conquer
以下解法还可做优化
class Solution {
public:
    vector<int> diffWaysToCompute(string s) {
        vector<int> rt;
        
        for (int i = 0; i < s.length(); i++) {
            if (s[i] == '-' || s[i] == '+' || s[i] == '*') {
                vector<int> first = diffWaysToCompute(s.substr(0,i));
                vector<int> second = diffWaysToCompute(s.substr(i + 1));
                for (int j = 0; j < first.size(); j++) {
                    for (int k = 0; k < second.size(); k++) {
                        if (s[i] == '-') {
                            rt.push_back(first[j] - second[k]);
                        }
                        if (s[i] == '+') {
                            rt.push_back(first[j] + second[k]);
                        }
                        if (s[i] == '*') {
                            rt.push_back(first[j] * second[k]);
                        }
                    }
                }
            }
        }
        if (rt.size() == 0) rt.push_back(stoi(s));
        return rt;
    }
};

DP优化
class Solution {
public:
    vector<int> helper(string s, int start, int end,unordered_map<string,vector<int>> &dic) {
        vector<int> rt;
        
        for (int i = start; i <= end; i++) {
            if (s[i] == '-' || s[i] == '+' || s[i] == '*') {
                vector<int> first;
                vector<int> second;
                if (dic.find(s.substr(start,i)) == dic.end()) {
                    first = helper(s,start,i - 1,dic);
                }else first = dic[s.substr(start,i)];
                
                if (dic.find(s.substr(i + 1)) == dic.end()) {
                    second = helper(s,i + 1,end,dic);
                }else second = dic[s.substr(i + 1)];
                
                for (int j = 0; j < first.size(); j++) {
                    for (int k = 0; k < second.size(); k++) {
                        if (s[i] == '-') {
                            rt.push_back(first[j] - second[k]);
                        }
                        if (s[i] == '+') {
                            rt.push_back(first[j] + second[k]);
                        }
                        if (s[i] == '*') {
                            rt.push_back(first[j] * second[k]);
                        }
                    }
                }
            }
        }
        if (rt.size() == 0) rt.push_back(stoi(s.substr(start,end - start + 1)));
        dic[s] = rt;
        return rt;
    }
    
    vector<int> diffWaysToCompute(string input) {
        unordered_map<string,vector<int>> dic;
        return helper(input,0,input.length() - 1,dic);
    }
};

Monday, August 10, 2015

Google interview questions #6

来自飞哥
给一堆interval,一个target(float),此api会被多次
第一问,问target有没有被cover到
按起点sort,然后mege。每次api都2分查找

第二问,target被几个interval cover
把原interval数组按起点排序,遇到overlap的,split重新构造interval,加入count
 1…3  2…5 --> 1…2 2…3 3…5, 每个interval都有对应的count,然后2分查找

interval都要先预处理

-----------------------------------------------------------------
REFhttp://www.mitbbs.com/article_t/JobHunting/33021975.html
听起来像是欧洲人,accent听起来有点吃力,先上题目:
1.leetcode上原题 number of islands
LC
2.follow up:count rank 2 islands, where a rank 2 island is an island inside
a lake located on a continent. A continent is a piece of land located in
the ocean; the ocean is any body of water that touches the edges of the map.

Example:
000000000
000001100
001111100
011000100
001010100
001000100
001111100
000000000
上面这个例子里应该返回1.

从4个边开始走,将所有连接的0染色,标为A,1染色,标为B。
从A继续走,找到相连接的1,染成C。
从C继续有,找到相连接的0,染成D
从D开始走,开始数岛的个数,返回

3.If the input 2d array is too large to fit in memory, how to handle?

我从第二个follow up开始就回答的磕磕绊绊,最后也没写code,一直在跟面试官讨论
。后来思路终于讨论出来了,但第二个follow up面试官提示说water的那个dfs和第一
问里的dfs有什么不同,后来明白他想说water的dfs要考虑对角线情况。第三个follow
up更是不知道怎么回答,瞎扯了一通。

请教各位大侠们,第三问该怎么考虑?


------------------------------------------------------------------------
REFhttp://www.mitbbs.com/mitbbs_article_t.php?board=JobHunting&gid=33030297&ftype=0
producer / consumer 问题, 要求threadsafe, high throughput
https://en.wikipedia.org/wiki/Monitor_(synchronization)
如何提高满足high throughput?
lock free queue: https://github.com/fat-lobyte/atomic_queue
Mutex m;
queue<Message> que;
CV Full;
CV Empty;

void producer(Message msg) {
    m.requireLock();
    while (que.full()) {
        wait(m,Full);
    }
    
    que.push(msg);
    signify(Empty);
    m.releaseLock();
}

Message consumer() {
    m.requireLock();
    while (que.empty()) {
        wait(m,Empty);
    }
    Message msg = que.front();
    que.pop();
    signify(Full);
    m.releaseLock();
    
    return msg;
}
----------------------------------------------------------
REFhttp://www.mitbbs.com/article_t/JobHunting/32939573.html
第一题merge n sorted list. 我用heap做,比较容易.

第二题
题目弄了半天大概搞清楚意思, 但是没做出来. 大家出来看一下怎么做.

有一个lock, 比如说1234

假设你要解锁, 你要尝试所有的combination来解锁, 怎么把这所有的combination存在
一个sequence里面使得sequence最短.

比如说锁只能是 0 1 2 组成的数字

锁是 1

012

锁是 12

sequence 可以是
000102101112202122
代表
00 01 02 10 11 12 20 21 22


也可以是, 如果你连着读的话
0011022120

可以代表
00
01
11
10
02
22
21
12
20

我觉得是怎么压缩这些candidate key到一个string里面

最优解巨难
https://en.wikipedia.org/wiki/De_Bruijn_sequence

普通解:dfs + backtrack,map记录出现过的密码,一个全部变量记录最短sequence


----------------------------------------------------------------------------------
ref: http://www.mitbbs.com/article_t/JobHunting/33031045.html 
Given a tree string expression in balanced parenthesis format:
(A(B(C)(D))(E)(F))

A
/ | \
B E F
/ \
C D

Return the corresponding tree (ie the root node). You can assume that the input is valid.

iterative的写法
struct TreeNode{
    char val;  
    vector<TreeNode*> children;
    TreeNode(char val) {
        this->val = val;    
    }
};


TreeNode *buildTree(string s) {
    stack<TreeNode *> st;
    TreeNode *root = NULL;
    for (int i = 0; i < s.length(); i++) {
        if (s[i] >= 'A' && s[i] <= 'Z') {
            TreeNode *node = new TreeNode(s[i]);
            st.push(node);
        }else if (s[i] == ')') {
            TreeNode *cur = st.top();
            st.pop();
            if (st.empty()) root = cur;
            else (st.top())->children.push_back(cur);
        }
    }
    
    return root;
}

另一种方法:类似level order traversal的DFS解法,但这里是iterative。
vector里存的是每一层的最后一个node,碰到‘(’, level + 1, 如果是‘)’,level - 1,
TreeNode *buildTree(string s) {
    vector<TreeNode *> ends;
    int level = 0;
    TreeNode *dummy = new TreeNode('d');
    ends.push_back(dummy);
    
    for (int i = 0; i < s.length(); i++) {
        if (s[i] == '(') {
            level++;    
        }else if (s[i] == ')') {
            level--;
        }else {
            TreeNode *node = new TreeNode(s[i]);    
            if (level >= ends.size()) {
                ends.push_back(node);
            }else {
                ends[level] = node;    
            }
            ends[level - 1]->children.push_back(node);
        }
    }
     
    return ends[1];
}
---------------------------------------------------------------------
REFhttp://www.mitbbs.com/article_t/JobHunting/32907123.html
1. Binary Search Tree, right next() function on each node
还有一个follow up question想不起来了
LC
2. Leetcode , merge interval 变种
find mean in two sorted list with same length
O(n) 扫一边
如果题目是find median in two sorted array with same length
http://www.geeksforgeeks.org/median-of-two-sorted-arrays/
double helper(vector<int> &v1,vector<int> &v2,int s1,int e1,int s2,int e2) {
    if (s1 == e1) return (v1[s1] + v2[s2]) / 2.0;
    int mid1 = (s1 + e1) / 2, mid2 = (s2 + e2) / 2;
    if (v1[mid1] == v2[mid2]) {
        return double(v1[mid1]);
    }

    if (e1 - s1 == 1) {
        return (max(v1[s1],v2[s2]) + min(v1[e1],v2[e2])) / 2.0;    
    }
    
    if (v1[mid1] < v2[mid2]) {
        return helper(v1,v2,mid1,e1,s2,mid2);
    }else {
        return helper(v1,v2,s1,mid1,mid2,e2);
    }
}

double findMedian(vector<int> &v1,vector<int> &v2) {
    return helper(v1,v2,0,v1.size() - 1,0,v2.size() - 1);
}


一个Design问题
3. 基本都是design的问题,design google recommendation
4. 设计/测试replicate cache的方法
5. 一个martrix,每行每列都是sorted,找到前kth 个
http://www.geeksforgeeks.org/kth-smallest-element-in-a-row-wise-and-column-wise-sorted-2d-array-set-1/
算法吊炸天!
#1 用一个大小为n的heap,初始存入第一行所有的值以及他们的row,col
#2 做一个长度为k的循环
每次弹出最小的值,之后压入被取出值的在同一列的下一个值
#3 heap里保存的是每一列的最小值,而且每次弹出的值是当前全局的最小值。所以k次之后出现的就是第k小的值

前四轮感觉都还可以,最后一轮是烙印,比较疲惫了,老觉得有一个什么最优解,后来
查了一下基本就是merge multiple sorted list的思路,做题的时候钻了牛角尖,老觉
得还有一个更好的解法。

---------------------------------------------------------
refhttp://www.mitbbs.com/article_t/JobHunting/33032299.html
一个matrix,每个matrix[i][j]有一个价格,给你一个budget,问如何求出最大面积的
子矩阵,使得子矩阵的价格之和不超过budget
没有想到特别好的解法

方法1:O(n^4), 枚举所有i, j为矩形的左右2列的矩阵
方法2:方法1的改进, O(n^3)
参考:http://www.geeksforgeeks.org/dynamic-programming-set-27-max-sum-rectangle-in-a-2d-matrix/

int kardane(vector<int> &temp) {
    int sum = temp[0];
    int curSum = temp[0];
    for (int i = 1; i < temp.size(); i++) {
        curSum = max(temp[i],curSum + temp[i]);
        sum = max(curSum,sum);
    }
    
    return sum;
}

int maxRectangles(vector<vector<int>> &matrix) {
    int m = matrix.size(), n = matrix[0].size();
    int largest = INT_MIN;
    vector<int> temp(m,0);
    
    for (int i = 0; i < n; i++) {
        vector<int> temp(m,0);
        for (int j = i; j < n; j++) {
            for (int row = 0; row < m; row++) {
                temp[row] += matrix[row][j];
            }
            
            largest = max(largest,kardane(temp));
        }
    }
    return largest;
}



---------------------------------------------------------------------------
FACEBOOK
refhttp://www.mitbbs.com/article_t/JobHunting/32617501.html

跳河问题。给一个0/1数组R代表一条河,0代表水,1代表石头。起始位置R[0]等于1,
初速度为1. 每一步可以选择以当前速度移动,或者当前速度加1再移动。只能停留在石
头上。问最少几步可以跳完整条河流。

给定数组为R=[1,1,1,0,1,1,0,0],最少3步能过河:
第一步先提速到2,再跳到R[2];
第二步先提速到3,再跳到R[5];
第三步保持速度3,跳出数组范围,成功过河。

假设有一方法 foo(int index,int speed) 返回从[index : ] 所需的最小步数
则:foo(index,speed) = 1 + min(foo(index + speed, speed), foo(index + speed + 1, speed + 1))
一些constraint:index需要为1,index + speed或+ 1也需要为1, index + speed + 1 < n
DP可解,O(N^2)
听说有更优解
int crossRiver(vector<int> &river) {
    int n = river.size();
    vector<vector<int>> dp(n,vector<int>(n,1));
    for (int i = n - 1; i >= 0; i--) {
        if (river[i] == 0) continue;
        for (int j = 1; j <= n; j++) {
            if (i + j + 1 < n) {
                if (river[i + j] == 0 && river[i + j + 1] == 0) {
                    dp[i][j] = INT_MAX;
                }else if (dp[i + j][j] != INT_MAX && dp[i + j + 1][j + 1] != INT_MAX) {
                    dp[i][j] = 1 + min(dp[i + j][j],dp[i + j + 1][j + 1]);
                }else if (dp[i + j][j] != INT_MAX) {
                    dp[i][j] = dp[i + j][j] + 1;
                }else {
                    dp[i][j] = dp[i + j + 1][j + 1] + 1;    
                }
            }
        }
    }

    return dp[0][1];
}