Thursday, July 23, 2015

Day 118, 240 Search a 2D Matrix II, Majority Number III

Search a 2D Matrix II
Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:
  • Integers in each row are sorted in ascending from left to right.
  • Integers in each column are sorted in ascending from top to bottom.
For example,
Consider the following matrix:
[
  [1,   4,  7, 11, 15],
  [2,   5,  8, 12, 19],
  [3,   6,  9, 16, 22],
  [10, 13, 14, 17, 24],
  [18, 21, 23, 26, 30]
]
Given target = 5, return true.
Given target = 20, return false.

---------------------------------------------------------------------------
REFhttp://articles.leetcode.com/2010/10/searching-2d-sorted-matrix-part-ii.html
O(n)
class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int m = matrix.size();
        int n = matrix[0].size();
        
        int row = 0, col = n - 1;
        while (row < m && col >= 0) {
            if (matrix[row][col] == target) return true;
            if (matrix[row][col] > target) {
                col--;
            }else {
                row++;
            }
        }
        
        return false;
    }
};

O((lgn)^2)
class Solution {
public:
    bool helper(vector<vector<int>>& matrix, int target,int rowStart,int rowEnd,int colStart,int colEnd) {
        if (rowStart > rowEnd || colStart > colEnd) {
            return false;
        }
        
        int row = (rowStart + rowEnd) / 2;
        int left = colStart,right = colEnd;
        while (left <= right) {
            int mid = (left + right) / 2;
            if (matrix[row][mid] == target) return true;
            if (matrix[row][mid] < target) {
                left = mid + 1;
            }else {
                right = mid - 1;
            }
        }
        
        return helper(matrix,target,rowStart,row - 1,right + 1,colEnd) 
                || helper(matrix,target,row + 1,rowEnd,colStart,right);
    }

    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int m = matrix.size();
        if (m == 0) return false;
        int n = matrix[0].size();
        
        return helper(matrix,target,0,m - 1,0,n - 1);
    }
};

Majority Number III
Given an array of integers and a number k, the majority number is the number that occurs more than 1/k of the size of the array.
Find it.
Have you met this question in a real interview? 
Yes
Example
Given [3,1,2,3,2,3,3,4,4,4] and k=3, return 3.
Note
There is only one majority number in the array.

Challenge
O(n) time and O(k) extra space
-------------------------------------------
用hash map来记录value跟count, 原理跟1、2相同
class Solution {
public:
    /**
     * @param nums: A list of integers
     * @param k: As described
     * @return: The majority number
     */
    int majorityNumber(vector<int> nums, int k) {
        // write your code here
        unordered_map<int,int> dic;
        
        for (int i = 0; i < nums.size(); i++) {
            if (dic.find(nums[i]) == dic.end()) {
                dic.insert(make_pair(nums[i],1));
            }else {
                dic[nums[i]]++;
            }
            
            if (dic.size() == k) {
             vector<int> t;
             for (auto kv : dic) {
              t.push_back(kv.first);
             }
             
                for (int i : t) {
                    dic[i]--;
                    if (dic[i] == 0) {
                        dic.erase(i);
                    }
                }
            }
        }
        
        unordered_map<int,int> left;
        int maxCount = 0, maxVal = 0;
        for (int i = 0; i < nums.size(); i++) {
            if (dic.find(nums[i]) != dic.end()) {
                if (left.find(nums[i]) == left.end()) {
                    left[nums[i]] = 1;
                }else {
                    left[nums[i]]++;
                }
                if (maxCount < left[nums[i]]) {
                    maxCount = left[nums[i]];
                    maxVal = nums[i];
                }
            }
        }
        
        return maxVal;
    }
};

Wednesday, July 22, 2015

Google interview questions #5

REF: http://www.mitbbs.com/article_t/JobHunting/33011505.html
Google
电面了2轮,题目有:
一个grid,点代表城市,边代表道路,输入是一个起始点跟一堆destination,还有哪些
路被blocked 打印所有能到的点
DFS或BFS都可以,开2d array或hashmap存visit信息

老题,2d matrix的row跟column都是sorted, 在里面搜某个数
LC #240 Search a 2D Matrix II 

oil pipeline problem, 下面这个链接的10.3-9
http://staff.ustc.edu.cn/~csli/graduate/algorithms/book6/chap10
找median, quick select(一种是常规的random pivot select,另一种是deterministic select,见algorithm课第3周)

补充问题是如果有2根pipeline,怎么放
找1/4 和 3/4的点

------------------------------------------------------------------------------
REF:http://www.mitbbs.com/article_t/JobHunting/33012223.html
1.一个字符串,从字典查出字符串所有单词,然后怎么提升效率,比如输入
whoisbillgates,返回['who', 'is','bill','gates']
Trie
2.N*N的矩阵,M个朋友随机住在矩阵上,求聚会地点,满足所有朋友总路程最短, lg复
杂度
如果是manhattan distance,找所以点的x的median跟y的median

3.树里的所有duplicated子树,O(n)遍历一次
in order遍历,把每个node的值给串成string,只要对比string就知道有没有重复的子树

string helper(vector<TreeNode *> &rt, TreeNode *root,unordered_set<string> &dic) {
    if (root == NULL) return "$"; // special char
    string s = helper(rt,root->left,dic);
    s += root->val;
    s += helper(rt,root->right,dic);

    if (dic.find(s) != dic.end()) {
        rt.push_back(root);
    }else {
        dic.insert(s);    
    }
    
    return s;
}

vector<TreeNode *> findDup(TreeNode *root) {
    unordered_set<string> dic;
    vector<TreeNode*> rt;
    helper(rt,root,dic);
    return rt;
}


4.BST,给定一个数值,返回BST中最接近的节点, lg n
binary search
void helper(TreeNode *root,int target,int &minVal,int &found) {
    if (root == NULL) return;
    if (abs(root->val - target) < minVal) {
            minVal = abs(root->val - target);
            found = root->val;
    }
    if (root->val < target) {
        helper(root->right,target,minVal,found);
    }else {
        helper(root->left,target,minVal,found);    
    }
}

int findClosest(TreeNode *root,int target) {
    int found = 0,minVal = INT_MAX;    
    helper(root,target,minVal,found);
    return found;
}

5.Minus one
类似plus one,特殊情况:当给出的数字为0时

6.一个整数链表,返回最长连续数字长度 o(n), 例如输入[10,6,2,15,5,9,1,3,100,4
],返回6,因为1-6是连续的
LC #128 longest consecutive sequence

7.一个矩阵,矩阵中节点为一个二元组,如果当前节点为M[a][b] =(x,y),下一个访问
节点为M[a+x][b+y],求从一点出发是否可以遍历矩阵
没啥可说的,O(n^2)
bool canGoAround(vector<vector<pair<int,int> > > &matrix,int row, int col) {
    int m = matrix.size();
    int n = matrix[0].size();
    vector<vector<bool> > visit(m,vector<bool>(n,false));
    int count = m * n;
    
    while (count > 0) {
        if (row < 0 || row == m || col < 0 || col == n || visit[row][col]) {
            return false;
        }
        visit[row][col] = true;
        row += matrix[row][col].first;
        col += matrix[row][col].second;
        count--;
    }
    
    return true;
}
8.判断任意两个人是否有血缘关系,自己定义person类
bfs, 加速的话可以同时从p1,p2出发

bool ifRelated(Person *p1, Person *p2) {
    queue<Person *> que;
    unordered_set<Person*> visit;
    que.push(p1);
    
    while (!que.empty()) {
        Person *me = que.front();
        que.pop();
        if (me == p2 || me->mom == p2 || me->dad == p2) return true;
        
        if (visit.find(me->mom) != visit.end()) {
            visit.insert(me->mom);
            que.push(me->mom);
        }
        if (visit.find(me->dad) != visit.end()) {
            visit.insert(me->dad);
            que.push(me->dad);
        }
        for (Person *k : me->kids) {
            if (k == p2) return true;
            if (visit.find(k) != visit.end()) {
                visit.insert(k);
                que.push(k);
            }
        }
    }
    
    return false;
}
--------------------------------------------------------------------------------
REF http://www.mitbbs.com/article_t/JobHunting/33011907.html
1. Given a robot and a maze, the robot supports these apis: Turn left, move forward, checkIsExit
Write a program to make it move to the exit
取决于题意,可能是给定一个矩阵,那就是简单的bfs或dfs
或者没有给定矩阵,不能标记,那得用pledge algorithm
https://en.wikipedia.org/wiki/Maze_solving_algorithm
http://site.douban.com/guokr/widget/notes/1670101/note/182257056/
https://www.youtube.com/watch?v=_KxAMV-2tKU
http://cs.stackexchange.com/questions/29705/maze-solving-algorithms-pledge-algorithm


2. Design Youtube access control system, storage, scales


3. Suppose there are k threads, write a multi-thread program to make them come to deadlock, I use semaphore at first, then was asked to implement itwith countDownLatch


4. RunLength encoding, discuss various ways to minimize the encoded string under different constraints


5. Design a system to generate Ids for distributed DBs, discuss various Zookeeper patterns (leader elections etc). For a given number, how to return minimum number of squares that sums up to this number



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

REF: http://www.mitbbs.com/article_t/JobHunting/33012339.html

题目:像apple tv,chrome tv之类的,用户可以搜索电影名字,但只能用remote在一

个虚拟的keyboard上搜索,只能在虚拟键盘上下左右移动。现在给定键盘如下:

a b c d e

f g h i j

k l m n o

p q r s t

u v w x y

z

如果用户要搜索电影名字为 cars,那么需要先往右走两步到c,输入enter,再往左走

两步到a,输入enter,再往下走3步往右走2步到r,输入enter,再往右走一步到s,输

入enter。现在规定L,R,U,D分部代表左,右,上,下移动一步,!代表输入enter,

那么用户动作可以表示成 RR!LL!DDDRR!R!

要求写一个函数,输入为一个string代表电影名字,输出为一个string代表用户的动作。

小印面试官,面了当天晚上给negative feedback,挂了。我面试中做的不好的是,没

有立马想到最佳solution,一开始提用bfs,被他否定后来提示下,想到用2d array坐

标,后来code写的还算顺利。但还是被小印无情的挂了。

对每个字母都坐标化,假设初始从‘a’开始
row = char / 5
col = char % 5
string helper(char move,int step) {
    string rt = "";
    for (int i = 0; i < step; i++) {
        rt += move;
    }
    
    return rt;
}

string fromOneLetterToAnother(char c1, char c2) {
    string move = "";
    int row1 = (c1 - 'a') / 5, col1 = (c1 - 'a') % 5;
    int row2 = (c2 - 'a') / 5, col2 = (c2 - 'a') % 5;
    // down
    if (row2 > row1) {
        move += helper('D',row2 - row1);
    }
    // up
    else if (row2 < row1) {
        move += helper('U',row1 - row2);
    }
    // R
    if (col2 > col1) {
        move += helper('R',col2 - col1);
    }
    // L
    else if (col2 < col1) {
        move += helper('L',col1 - col2);
    }
    
    return move;
}

string movement(string input) {
    string output = "";
    char pre = 'a';
    
    for (int i = 0; i < input.length(); i++) {
        output += fromOneLetterToAnother(pre,input[i]) + "!";
        pre = input[i];
    }
    
    return output;
}

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

REF: http://www.mitbbs.com/article_t/JobHunting/32933923.html
1. Wildcard match
LC原题

2. http://www.fgdsb.com/2015/01/25/peek-iterator/类似。写一个de duplicator,wrap 几个stream,输出的stream全是不重复数字。
hash所有输出的结果
class It{
public:
    It(vector<int> &data) {
        ptr = 0;
        this->data = data;
    }
    It() {}
    
    bool has_next() {
        return ptr < data.size();
    }
    int get_next() {
        int rt = data[ptr];
        ptr++;
        return rt;
    }

private:
    vector<int> data;
    int ptr;
};

class Deduplicator{
public:    
    Deduplicator(vector<int> &data) {
        it = It(data);
    }

    int get_next() {   
        if (!st.empty()) {
            int rt = st.top();
            st.pop();
            return rt;
        }
        
        if (!has_next()) {
            return -1;    
        }
        int rt = st.top();
        st.pop();
        return rt;
    }

    bool has_next() {
        if (!st.empty()) {
            return true;
        }
        
        if (!it.has_next()) return false;
        int rt = it.get_next();
        while (dic.find(rt) != dic.end()) {
            if (it.has_next()) {
                rt = it.get_next();
            }else {
                return false;    
            }
        }
        dic.insert(rt);
        st.push(rt);
        return true;
    }

    
private:
    It it;
    unordered_set<int> dic;
    stack<int> st;
};

3. 求一个stream,出现次数最多的数字。然后扩展到N个machine的情况。
系统设计题
#1 储存:单机存不下,有一个(或多个)master专门用来收数字,然后分发到N个机子上,
也可以是环状结构(类似consistent hashing),各机器自己处理接受,然后发到其他机器
#2 计算:各机器自己计算,汇报给其中一台

4. 假设某个company在不同国家都有office,每个国家的office,如果是当地的假期,
就可以放假了。假设可以查询任意航班的信息,每个星期只能呆在一个地方,只有周末
的时候才能飞去别的国家。找一个放假天数最多的schedule。
这题够开放!
假期,输入可为:n个国家 of 54周 of 假期个数
航班,输入可为:54个n * n 2d数组
对每个国家的星期按假期数量排序,按dfs或bfs走都可,每条path都要走一遍才能得出最多假期

输出为一个path

5. LRU + 一些 C++问题。
LC原题

6. 这题记不大清楚了。好像是Longest increasing consecutive sequence, 然后一
个Tree的该进版。求longest increasing consecutive path。
Longest Increasing Continuous subsequence
Longest Increasing Continuous subsequence II 2d数组
Longest Increasing Subsequence


7. file system design。就是设计一个大数据的存取问题。存在disk上。我就是
partition + hash + cache那一套糊弄过去了。

Friday, July 17, 2015

Coursera - Algorithms: Design and Analysis, Part 1

Week 1 - Question 1 
Download the text file here. (Right click and save link as) This file contains all of the 100,000 integers between 1 and 100,000 (inclusive) in some order, with no integer repeated. Your task is to compute the number of inversions in the file given, where the ith row of the file indicates the ith entry of an array. Because of the large size of this array, you should implement the fast divide-and-conquer algorithm covered in the video lectures. The numeric answer for the given input file should be typed in the space below. So if your answer is 1198233847, then just type 1198233847 in the space provided without any space / commas / any other punctuation marks. You can make up to 5 attempts, and we'll use the best one for grading. (We do not require you to submit your code, so feel free to use any programming language you want --- just type the final numeric answer in the following space.) [TIP: before submitting, first test the correctness of your program on some small test files or your own devising. Then post your best test cases to the discussion forums to help your fellow students!]

count inversion, 基本的merge sort嵌入count
vector<int> merge(vector<int> p1,vector<int> p2,long long &count) {
    vector<int> rt;
    int i = 0, j = 0;
    while (i < p1.size() && j < p2.size()) {
        if (p1[i] < p2[j]) {
            rt.push_back(p1[i]);
            count += j;
            i++;
        }else {
            rt.push_back(p2[j]);
            count += (p1.size() - i);
            j++;
        }
    }
    
    while (i < p1.size()) {
        rt.push_back(p1[i]);
        i++;
        count += j;
    }
    while (j < p2.size()) {
        rt.push_back(p2[j]);
        j++;
    }
    
    return rt;
}

vector<int> mergeSort(vector<int> &nums,int start, int end,long long &count) {
    if (start == end) {
        vector<int> rt(1,nums[start]);
        return rt;
    }
    int mid = (start + end) / 2;
    vector<int> part1 = mergeSort(nums,start,mid,count);
    vector<int> part2 = mergeSort(nums,mid + 1,end,count);
    return merge(part1,part2,count);
}

long long countInversions(vector<int> &nums) {
    long long count = 0;
    vector<int> v = mergeSort(nums,0,nums.size() - 1,count);
    return count / 2;
}
------------------------------------
closest pair of points
class Point{
public:
    int x;
    int y;
};


bool cmpX(Point &p1, Point &p2) {
    return p1.x < p2.x;
}

bool cmpY(Point &p1, Point &p2) {
    return p1.y < p2.y;
}

float bruteForce(vector<Point> &p, int left, int right) {
    // brubute force when there are lessn than 3 nodes
}

float getDistance(Point p1, Point p2) {
    // distance between two points
}

float split(vector<Point> &p,vector<Point> &q, int mid,int minD) {
    vector<Point> strip;
    for (int i = 0; i < strip.size(); i++) {
        if (fabs(strip[i].x - p[mid].x) < minD) {
            strip.push_back(strip[i]);
        }
    }
 
 // 7 position head in y-coordinates is enough
    for (int i = 0; strip.size() - 1; i++) {
        for (int j = i + 1; j <= i + 7 || j < strip.size()) {
            minD = min(minD,getDistance(strip[i],strip[j]));
        }
    }
 
    return midD;
}

float helper(vector<Point> &p,vector<Point> &q,int left,int right) {
    if (right - left <= 3) {
        return bruteForce(p,left,right);
    }
 
    int mid = (left + right) / 2;
    float minDistance = min(helper(p,left,mid), helper(p,mid,right));
 
    return min(minDistance,split(p,mid,minDistance));
}

float closestPair(vector<Point> &p) {
    sort(p.begin(),p.end(),cmpX);
    vector<int> q = p;
    sort(q.begin(),sortByY.end(),cmpY);
 
    helper(p,q,0,p.size() - 1);
}

-------------------------------------------------------------------------------------
  1. [Posted June 29th] You are given as input an unsorted array of n distinct numbers, where n is a power of 2. Give an algorithm that identifies the second-largest number in the array, and that uses at most n+log2n−2 comparisons. 
  2. [Posted June 29th] You are a given a unimodal array of n distinct elements, meaning that its entries are in increasing order up until its maximum element, after which its elements are in decreasing order. Give an algorithm to compute the maximum element that runs in O(log n) time. 找rotated array里的最大值
  3. [Posted June 29th] You are given a sorted (from smallest to largest) array A of n distinct integers which can be positive, negative, or zero. You want to decide whether or not there is an index i such that A[i] = i. Design the fastest algorithm that you can for solving this problem. 2分取中点,如果i大于A[i], 往右走。如果小,往左走
  4. [Posted June 29th] Give the best upper bound that you can on the solution to the following recurrence: T(1)=1 and T(n)≤T([n−−√])+1 for n>1. (Here [x] denotes the "floor" function, which rounds down to the nearest integer.) 
  5. [Posted June 29th] You are given an n by n grid of distinct numbers. A number is a local minimum if it is smaller than all of its neighbors. (A neighbor of a number is one immediately above, below, to the left, or the right. Most numbers have four neighbors; numbers on the side have three; the four corners have two.) Use the divide-and-conquer algorithm design paradigm to compute a local minimum with only O(n) comparisons between pairs of numbers. (Note: since there are n2 numbers in the input, you cannot afford to look at all of them. Hint: Think about what types of recurrences would give you the desired upper bound.) find peak

--------------------------------------------------------------------------
Week 2
Notes:

Tuesday, July 14, 2015

Day 117, #235, #236, Lowest Common Ancestor of a Binary Search Tree, Lowest Common Ancestor of a Binary Tree

Lowest Common Ancestor of a Binary Search Tree
Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST.
According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes v and w as the lowest node in T that has both v and w as descendants (where we allow a node to be a descendant of itself).”
        _______6______
       /              \
    ___2__          ___8__
   /      \        /      \
   0      _4       7       9
         /  \
         3   5
For example, the lowest common ancestor (LCA) of nodes 2 and 8 is 6. Another example is LCA of nodes 2 and 4 is 2, since a node can be a descendant of itself according to the LCA definition.

-------------------------------------------------------------------------
/**
 * 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:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if ((root->val >= p->val && root->val <= q->val) || (root->val <= p->val && root->val >= q->val)) return root;
        if (root->val > p->val) {
            return lowestCommonAncestor(root->left,p,q);
        }else {
            return lowestCommonAncestor(root->right,p,q);
        }
    }
};

Lowest Common Ancestor of a Binary Tree
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.
According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes v and w as the lowest node in T that has both v and w as descendants (where we allow a node to be a descendant of itself).”
        _______3______
       /              \
    ___5__          ___1__
   /      \        /      \
   6      _2       0       8
         /  \
         7   4
For example, the lowest common ancestor (LCA) of nodes 5 and 1 is 3. Another example is LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition.
----------------------------------------------
/**
 * 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:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if (root == NULL || root == q || root == p) return root;
        TreeNode *left = lowestCommonAncestor(root->left,p,q);
        TreeNode *right = lowestCommonAncestor(root->right,p,q);
        
        if (left != NULL && right != NULL) return root;
        if (left == NULL) return right;
        return left;
    }
};


Google interview questions #4

REF http://www.1point3acres.com/bbs/forum.php?mod=viewthread&tid=136847&extra=page%3D1%26filter%3Dsortid%26sortid%3D311%26sortid%3D311
给我小哥没有废话直接上题
我coding速度太慢,只面了一道题目
.鐣欏璁哄潧-涓€浜�-涓夊垎鍦�
给出一个迭代器,迭代器里存了很多个类R的实例, 类R里只有两个参数,都是String类型,分别代表Parent 和 Child,child只有一个Parent,Parent 可以有任意数量child
按所给示例输出所有的层级关系

eg:
A
  B1
  B2
    C1
    C2
  B3
    D1. 1point3acres.com/bbs
    D2. 1point3acres.com/bbs


就是建立一个compiler里面的inheritance graph,然后打印
struct TreeNode{
    string parent;
    string name;
    vector<TreeNode *> children;
    TreeNode(string p, string n) {
        parent = p;
        name = n;
    }
};
class A{
    public:
    string parent;
    string child;
};
void printRecursively(TreeNode *root, string tab) {
    if (root == NULL) return;
    cout << tab << root->name << endl;
    for (int i = 0; i < root->children.size(); i++) {
        printRecursively(root->children[i],tab + " ");
    }
}
void printGraph(vector<A> &source) {
    unordered_map<string,TreeNode*> dic;
    for (int i = 0; i < source.size(); i++) {
        TreeNode *p = NULL, *c = NULL;
        if (dic.find(source[i].parent) == dic.end()) {
            p = new TreeNode("",source[i].parent);
            dic[source[i].parent] = p;
        }
        if (dic.find(source[i].child) == dic.end()) {
            c = new TreeNode(source[i].parent,source[i].child);
            dic[source[i].child] = c;
        }
        p = dic[source[i].parent];
        c = dic[source[i].child];
        p->children.push_back(c);
    }
    for (auto t : dic) {
        if (dic[t.first]->parent.length() == 0) {
            printRecursively(dic[t.first],"");
        }
    }
}
int main()
{
    A a1;
    a1.parent = "A";
    a1.child = "B1";
    A a2;
    a2.parent = "A";
    a2.child = "B2";
    A a3;
    a3.parent = "A";
    a3.child = "B3";
    A b1;
    b1.parent = "B2";
    b1.child = "C1";
    A b2;
    b2.parent = "B2";
    b2.child = "C2";
    A c1;
    c1.parent = "B3";
    c1.child = "D1";
    A c2;
    c2.parent = "B3";
    c2.child = "D2";
    vector<A> v;
    v.push_back(a1);
    v.push_back(a2);
    v.push_back(a3);
    v.push_back(b1);
    v.push_back(b2);
    v.push_back(c1);
    v.push_back(c2);
    printGraph(v);
}

---------------------------------------------------------------------------------------
REF http://www.1point3acres.com/bbs/forum.php?mod=viewthread&tid=134335&extra=page%3D1%26filter%3Dsortid%26sortid%3D311%26sortid%3D311
4月底MTV面的onsite, 很奇怪是5面,至今没消息,直接上面经
鏉ユ簮涓€浜�.涓夊垎鍦拌鍧�. 
1.日本大叔-google 1point3acres
来晚了20分钟导致后面很紧。先写反转链表,然后第二题把链表变成a1->an->a2->an-1
LC reorder list
2.白人小哥+沉默的阿三
第一题是path sum难度一样的dp水果。 第二题给画布上的几个线段,问怎么画最快(移动画笔会浪费时间). Waral 鍗氬鏈夋洿澶氭枃绔�,
待写
3.阿三
到这面的时候才20分钟后面找我吃饭的大叔就来了,草草写完,给一个字符串,问可否组成一个新串使得每两个相邻字符不重复
重复,见Google interview questions #2 onsite第1题
. Waral 鍗氬鏈夋洿澶氭枃绔�,
午饭是个黑叔叔,用手直接抓食物吃,震精

4.光头小白
先问简历,然后又是一个path sum难度一样的dp水果


5.白人小帅
q: 玩过扫雷吗?
a: yes
q: 实现它
a: wtf??
http://www.careercup.com/question?id=11966706
#1 生成地图
给定2维数组,雷的个数为 x / (n * m), x自定义,随机放雷,不重复
生成数字

#2 玩家点击(设置额外数组)
右键:标记
左键:
双击:检测周边的雷是否还没被扫光

#3 胜利失败条件



-------------------------------------------------------------------------- REF http://www.1point3acres.com/bbs/forum.php?mod=viewthread&tid=137928&extra=page%3D1%26filter%3Dsortid%26sortid%3D311%26sortid%3D311
可能是因为我做得慢,总共就做了一道题,就是一个游戏。 
input string:“+++--++-+”
游戏规则:每人每次可以 flip "++" to "--"(必须是相邻的)


第一问:generate all possible moves
第二问:determine if this player can will
Extra:这两个问题的implementation的Big-O

补充内容 (2015-7-12 13:13):
下个人没法flip了这个人就赢;all possible moves for next flip
permutation,  O(n!) 
T(n) = T(n - 1) + T(n - 1) + T(n - 1)...... + c = (n - 1) * T(n - 1) + c
T(n - 1) = (n - 2) * T(n - 2)
T(n - 2) = (n - 3) * T(n - 2)
.....
So T(n) = n!

bool canWin(string s) {
    int start = -1,end = -1;
    for (int i = 0;
    i < s.length();
    i++) {
        if (s[i] == '+') {
            if (start != -1 && i - start > 0) {
                string t = s;
                t[start] = '-';
                t[i] = '-';
                if (!canWin(t)) return true;
                start++;
                }else {
                start = i;
            }
            }else {
            start = -1;
        }
    }
    return false;
}

另一方法:博弈论,可达到O(n^2), 关键词game theory, nimber, grundy number

http://www.1point3acres.com/bbs/thread-137953-1-1.html
----------------------------------------------------------------------------------------
Linked List e.g 1->5->2->3->7
Modify it so that it becomes: 1->7->5->3->2
一头一尾,第二头第二尾,O(1)空间复杂度,O(n)时间复杂度
-----------------------------------------------------------------------------------

  Given a bunch of N random points in space, how would you draw a line such that N/2 of them were to the left of the line and N/2 to the right of it. Complexity 

按x坐标用quick select,找出median,只需要O(n) 
-------------------------------------------------
Given an unbalanced binary tree, write code to select a node at random (each node has an equal probability of being selected).
reservoir sampling
void helper(TreeNode *root, int &count, int choice) {
    if (root == NULL) return NULL;
    count++;
    if (rand(1,count) == 1) {
        choice = root;
    }
    helper(root->left,count,choice);
    helper(root->right,count,choice);
}

TreeNode *findRandomNode(TreeNode *root) {
    TreeNode *choice = NULL;
    int count = 0;
    return helper(root,count,choice);
}



------------------------------
给一个array和target,找出在array里与target最接近的值的index
类似LC search insert position
int getSmallest(int i, int j) {
    for (int s = 1; s <= j; s++) {
        if (s * i % j == 0) return s * i;
    }
}

int jumpBack(vector<int> &shuffle) {
    vector<int> visit(shuffle.size(),-1);
    int count = 0, preCount = 1;
    for (int i = 0; i < shuffle.size(); i++) {
        count = 0;
        int index = i;
        while (visit[index] == -1) {
            count++;
            visit[index] = shuffle[i];
            index = shuffle[index];
            if (visit[index] != -1 && visit[index] != visit[i]) return -1;
        }
        if (count != 0) preCount = getSmallest(count,preCount);
    }
    return preCount;
}


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

REF http://www.mitbbs.com/article_t/JobHunting/33010083.html
onsite
1. card shuffler:shuffle的程序是一个简单的array,array里的值代表当前位置卡
片的下一个位置 
e.g 当前卡片位置ABCDE shuffle array是01234的话下个卡片位置还是ABCDE,43210的
话下个卡片位置是EDCBA。
问给定一个shuffle array,不断用这个array去shuffle,能否得到最初的card deck,
能得话要多少次。 
吐槽下,面试官是个三哥,全程非常严肃/黑脸,我说句话就用小本子记下搞得我很紧
张。我说用java写可以吗,曰可以,刚写了两行问我add是啥意思,不知道是想考我基
础知识还是不懂java。

O(n), 对shuffle里面的每一个点都走一遍,最后走回起始点,走过的路径全部mark起来,记录count。mark过的可以直接跳过
最后取所以count的最小公约数即可

2. 给定一个binary search tree,返回range内所有key,key可以有重复。 
版上出现了多次的把一个数拆成任意个平方和的最小拆法。
DP,重复
面试官是中年国人大叔,除了告诉我题目是啥就在电脑上自顾自工作,问话要问两遍才
有反应。写完说我程序有问题,查了半天查不出bug,然后指出我漏了个尖括号,跪了
。。

3. 版上出现多次的longest consecutive sequence in tree 
follow up 如何加速,memory放不下怎么办。
国人小哥比较nice,但是只要我不和他主动说话绝不主动和我说话,因为前两场心情略
糟糕写完题目在白板前发呆,哥们就望着我啥也不说,尴尬。。当然也不怪他我自己比
较紧张,回家发现有很弱智的bug但小哥没提不知道怎么回事,可能放我水了
跟LC #128 Longest Consecutive Sequence 类似
对于follow up,hashmap<int,int>里可只记录范围,将范围内的都删掉省空间,但是如果给定的数组或树内有重复元素,则次方法不适用


4. 设计个用bit形式表示时间(小时:分钟)的clock,
e.g 10:15可以写作1010:1111,每个bit是一个小灯泡,打印所有有且仅有n盏灯亮着的
时间,
e.g. n=0就只有0:0一种可能。

面试官是亚裔年轻mm,话不多人很cool,但是思路清晰会引导面试者,感觉碰到懂得引
导面试者或冷漠面试官对面试人表现会有很大影响,真的是看运气了。
permutation,遍历写法
int countOnes(int num) {
    int count = 0;
    while (num > 0) {
        count++;
        int twosC = ~num + 1;
        num = (~(twosC & num)) & num;
    }
    
    return count;
}

string toBinary(int num) {
    string bi = "";
    while (num > 0) {
        char c = (num % 2) + '0';
        bi = c + bi;
        num /= 2;
    }
    if (bi.length() == 0) return "0";
    return bi;
}

vector<vector<int> > precompute() {
    vector<vector<int> > table(6);
    
    for (int i = 0; i < 60; i++) {
        int count = countOnes(i);
        table[count].push_back(i);
    }
    return table;
}


void printPermutation(int n) {
    vector<vector<int> > table = precompute();
    vector<string> rt;
    
    for (int i = 0; i <= n; i++) {
        for (int j = 0; j < table[i].size(); j++) {
            for (int k = 0; k < table[n - i].size(); k++) {
                if (table[i][j] < 24) {
                    rt.push_back(toBinary(table[i][j]) + ":" + toBinary(table[n - i][k]));   
                }
            }
        }
    }
}

#1 递归的解法,注意插入rt时的条件,仅仅只是 n == 0,如果加上 && index == 6,则将会过滤掉10,100,1000。。。等等case
#2 string "0"与”00“要是重复,要过滤掉
int toNum(string bi) {
    int num = 0;
    for (int i = 0; i < bi.length(); i++) {
        num = num * 2 + bi[i] - '0';
    }
    
    return num;
}

void computeMinute(vector<string> &rt,int n, string s,int index) {
    if (n < 0 || index > 6 || toNum(s) > 59) return;
    if (n == 0) {
        rt.push_back(s);
    }
    
    if (s != "0") {
        computeMinute(rt,n,s + '0',index + 1);
        computeMinute(rt,n - 1,s + '1',index + 1);
    }else {
        computeMinute(rt,n - 1,"1",index + 1);
    }
}

void computeHour(vector<string> &rt,int n, string s,int index) {
    if (n < 0 || index > 5 || toNum(s) > 23) return;
    vector<string> mins;
    computeMinute(mins,n,"0",0);
    
    for (int i = 0; i < mins.size(); i++) {
        rt.push_back(s + ":" + mins[i]);
    }
    
    if (s != "0") {
        computeHour(rt,n,s + '0',index + 1);
        computeHour(rt,n - 1,s + '1',index + 1);
    }else {
        computeHour(rt,n - 1,"1",index + 1);
    }
}

vector<string> printPer1(int n) {
    vector<string> rt;
    computeHour(rt,n,"0",0);
    return rt;
}

5.算法游戏,给一个只有+-两种字符的array,两个玩家,轮到某个玩家他可以任选
两个连续的--将他们变成++,如果某个玩家发现自己无法行动则赢得游戏,要求写
isWin(String s)判断先行动的玩家能否赢。
followup 如何优化,时间上和空间上。
面试官是做android前端的白人mm,非常活泼健谈,一路聊天愉快,面完就感觉她会给
强推。
重复

Thursday, July 9, 2015

Day 116, #231, #232, #234, Power of Two, Implement Queue using Stacks, Palindrome Linked List, Number of Digit One

Power of Two
Given an integer, write a function to determine if it is a power of two.
----------------------------------------------------------------------
class Solution {
public:
    bool isPowerOfTwo(int n) {
        if (n <= 0) return false;
        return !(n & (n - 1));
    }
};

Implement Queue using Stacks
Implement the following operations of a queue using stacks.
  • push(x) -- Push element x to the back of queue.
  • pop() -- Removes the element from in front of queue.
  • peek() -- Get the front element.
  • empty() -- Return whether the queue is empty.
Notes:
  • You must use only standard operations of a stack -- which means only push to toppeek/pop from topsize, and is empty operations are valid.
  • Depending on your language, stack may not be supported natively. You may simulate a stack by using a list or deque (double-ended queue), as long as you use only standard operations of a stack.
  • You may assume that all operations are valid (for example, no pop or peek operations will be called on an empty queue).
---------------------------------------------
只有当output stack为空时,才会将input里的数全部压入output,抄的
class Queue {
public:
    // Push element x to the back of queue.
    void push(int x) {
        input.push(x);
    }

    // Removes the element from in front of queue.
    void pop(void) {
        peek();
        output.pop();
    }

    // Get the front element.
    int peek(void) {
        if (output.empty()) {
            while (!input.empty()) {
                output.push(input.top());
                input.pop();
            }
        }
        return output.top();
    }

    // Return whether the queue is empty.
    bool empty(void) {
        return input.empty() && output.empty();
    }
private:
    stack<int> input;
    stack<int> output;
};

Palindrome Linked List
Given a singly linked list, determine if it is a palindrome.
Follow up:
Could you do it in O(n) time and O(1) space?
-----------------------------------------------
找到中点,翻转其中一半,再比较
slow是中点(odd number)或者是后半部分的启示(even)
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        if (head == NULL) return true;
        ListNode *fast = head, *slow = head;
        while (fast != NULL) {
            fast = fast->next;
            if (fast != NULL) {
                fast = fast->next;
                slow = slow->next;
            }
        }
        
        // reverse the second half
        ListNode *newHead = NULL;
        while (slow != NULL) {
            ListNode *temp = slow->next;
            slow->next = newHead;
            newHead = slow;
            slow = temp;
        }
        
        while (newHead != NULL) {
            if (newHead->val != head->val) return false;
            newHead = newHead->next;
            head = head->next;
        }
        
        return true;
    }
};

Number of Digit One
Given an integer n, count the total number of digit 1 appearing in all non-negative integers less than or equal to n.
For example:
Given n = 13,
Return 6, because digit 1 occurred in the following numbers: 1, 10, 11, 12, 13.
Hint:
  1. Beware of overflow.
--------------------------------------------------------------
对每一位上的1可能出现的次数进行统计
refhttp://blog.csdn.net/xudli/article/details/46798619
class Solution {
public:
    int countDigitOne(int n) {
        int rt = 0;
        
        for (long long i = 1; i <= n; i *= 10) {
            int left = n / i;
            int right = n % i; // 当前位之后的数
            int cur = left % 10; // 当前位上的数
            left /= 10;  // 当前位之前的数
            
            if (cur == 0) {
                rt += left * i;
            }else if (cur == 1) {
                rt += left * i + right + 1;
            }else {
                rt += (left + 1) * i;
            }
        }
        
        return rt;
    }
};

Tuesday, July 7, 2015

Google interview questions #3

REFhttp://www.mitbbs.com/article_t/JobHunting/32992983.html
1. find all rotation symmetric numbers less than N digits,  16891 -> 16891, 

类似LC #246 Strobogrammatic Number 

对称性,11,00,88,69,96. 当n为奇数时,中间为1,8,或0
假设n为位数,k为n位数时rotation symmetric numbers的数量,则:
n = 1, k = 3
n = 2, k = 5
n = 3, k = 3 * 5
n = 4, k = 5 * 5
n = 5, k = 3 * 5 * 5
n = 6, k = 5 * 5 * 5
....

void insertToReturn(vector<string> &rt, vector<string> candidates) {
    for (int i = 0; i < candidates.size(); i++) {
        rt.push_back(candidates[i]);
    }  
}

vector<string> pad(vector<string> candidates) {
    vector<string> rt;
    for (int i = 0; i < candidates.size(); i++) {
        rt.push_back("1" + candidates[i] + "1");
        rt.push_back("8" + candidates[i] + "8");
        rt.push_back("0" + candidates[i] + "0");
        rt.push_back("6" + candidates[i] + "9");
        rt.push_back("9" + candidates[i] + "6");
    }
  
    return rt;
}

vector<string> findAllNumber(int n) {
    vector<string> odd;
    vector<string> even;
    odd.push_back("1");
    odd.push_back("8");
    odd.push_back("0");
    even.push_back("11");
    even.push_back("88");
    even.push_back("00");
    even.push_back("69");
    even.push_back("96");
    
    if (n == 1) return odd;
    if (n == 2) {
        insertToReturn(odd,even);
        return odd;
    }
    
    vector<string> rt;
    insertToReturn(rt,odd);
    insertToReturn(rt,even);
    
    for (int i = 3; i <= n; i++) {
        if (i % 2 == 1) {
            odd = pad(odd);
            insertToReturn(rt,odd);
            
        }else {
            even = pad(even);
            insertToReturn(rt,even);
        }
    }
    
    return rt;
}

2. give integer, 12345, 返回 32154
先把integer转为string,然后前半部分翻转,再后半部分翻转
或直接数一下integer一共多少位
    give a target  string and list of strings, find the longest string that 
has target as prefix, follow up, stream of target string, 用trie,每个节点保
留最长string信息。
3. integer array add one
    rotation abc->bcd->cde, give a list of strings, group them if them are 
rotations.
居然给我laptop,然后直接上面写,然后debug通过,给test case通过

4. given grid of colors, coordinate of a point and its color, find the 
perimeter of the region that has the same color of that point.
BFS或DFS,构成perimeter的条件是只要上下左右有一个不是同颜色或者是out of bound
用一个set记录visit的信息
    print all morse code given the length constraints, short “*” takes one
, long “——“takes two. (find a bug in the code) 就是排列组合的典型题
5. design: chromecast, how to know which app can be supported? There is a 
cloud that can give the information to the chrome cast, appID, deviceID, 
cache design. 
---------------------------------------------------------------
REF: http://www.mitbbs.com/article_t/JobHunting/32882153.html
continental divider
给一个矩阵,其中0代表海洋,其他数字代表高度,秉着水往低处流的原则,求出能够
流向任意海洋的点。 比如说
0 0 0 1 2 3 0
0 1 2 2 4 3 2
2 1 1 3 3 2 0
0 3 3 3 2 3 3

那么就要给出 第二行的4 (这有这点出发,能够找到连通道四个0的区域的一条非递增
路线),当然也有可能找不到这样的点,或者找到多个点。
对每一个ocean,找出所有它能流通的山脉,然后在相应的位置上 + 1,
最后对比所有位置上的数与ocean的个数
void dfs(vector<vector<int> > &grid,vector<vector<int> > &count,vector<vector<bool>> &visit,int row,int col,int pre) {
    if (row < 0 || row >= grid.size() || col < 0 || col >= grid[0].size() || visit[row][col]) {
        return;
    }
    
    visit[row][col] = true;
    if (grid[row][col] != 0 && grid[row][col] < pre) {
        return;
    }
    count[row][col]++;
    //cout << row << " " << col << endl;
    dfs(grid,count,visit,row + 1,col,grid[row][col]);
    dfs(grid,count,visit,row - 1,col,grid[row][col]);
    dfs(grid,count,visit,row,col + 1,grid[row][col]);
    dfs(grid,count,visit,row,col - 1,grid[row][col]);
    
}


bool flow(vector<vector<int>> &grid) {
    int m = grid.size();
    int n = grid[0].size();
    vector<vector<int>> count(m,vector<int>(n,0));
    int oceanSize = 0;
    
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            if (grid[i][j] == 0) {
                vector<vector<bool>> visit(m,vector<bool>(n,false));
                oceanSize++;
                dfs(grid,count,visit,i,j,0);
            }
        }
    } 
    
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            if (count[i][j] == oceanSize) {
                cout << i << " " << j << endl;
            }
        }
    }
}
--------------------------------------------------------------------
REF http://www.mitbbs.com/article_t1/JobHunting/33004699_0_1.html
1. 二维matrix,含0,1。  1是障碍。
  00011
  11100 
  从左上角出发到右下角, 可以往上,往下,往右移动。
  把1变成0,使得你可以从左上角到右下角。
  求最小的变化数字。
2个角度(dfs / bfs)
#1 找出所有路径中,含1最少的那个路径
#2 最短路径,每个路径weight为0或者1, dijkstra

Dijkstra为O(n*lgn),可用2个queue降低复杂度为O(n)。因为edge的weight只为0或1
bool bfs(vector<vector<int> > &grid,vector<vector<bool> > &visit,queue<pair<int,int>> &q1,queue<pair<int,int>> &q2) {
    while (!q1.empty()) {
        int row = q1.front().first;
        int col = q1.front().second;
        if (row == grid.size() - 1 && col == grid[0].size() - 1) {
            return true;    
        }
        q1.pop();
        
        if (row + 1 < grid.size() && !visit[row + 1][col]) {
            visit[row + 1][col] = true;
            if (grid[row + 1][col] == 0) {
                q1.push(make_pair(row + 1,col));
            }else {
                q2.push(make_pair(row + 1,col));    
            }
        }
        if (row - 1 >= 0 && !visit[row - 1][col]) {
            visit[row - 1][col] = true;
            if (grid[row - 1][col] == 0) {
                q1.push(make_pair(row - 1,col));
            }else {
                q2.push(make_pair(row - 1,col));    
            }   
        }
        if (col + 1 < grid[0].size() && !visit[row][col + 1]) {
            visit[row][col + 1] = true;
            if (grid[row][col + 1] == 0) {
                q1.push(make_pair(row,col + 1));
            }else {
                q2.push(make_pair(row,col + 1));    
            }
        }
        if (col - 1 >= 0 && !visit[row][col - 1]) {
            visit[row][col - 1] = true;
            if (grid[row][col - 1] == 0) {
                q1.push(make_pair(row,col - 1));
            }else {
                q2.push(make_pair(row,col - 1));    
            }   
        }
        
    }
    
    
    return false;
}

int findPath(vector<vector<int> > &grid) {
    int m = grid.size();
    int n = grid[0].size();
    queue<pair<int,int>> q1;
    queue<pair<int,int>> q2;
    int count = 0;
    q1.push(make_pair(0,0));
    
    vector<vector<bool> > visit(m,vector<bool>(n,false));
    visit[0][0] = true;
    
    while (!q1.empty()) {
        if (bfs(grid,visit,q1,q2)) {
            return count;
        }
        count++;
        queue<pair<int,int>> empty;
        q1 = q2;
        swap(q2,empty);
    }
    
    return -1;
}

2。 两个区间,左闭右开。数字可以是整数或者浮点,
     要你判断两个区间是否相交。
     特殊例子需要你自己定义。