Saturday, October 31, 2015

Day 132, #287 #290 #291 #292 #296 Find the Duplicate Number, Word Pattern, Word Pattern II, Nim Game, Best Meeting Point

Find the Duplicate Number
 Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), prove that at least one duplicate number must exist. Assume that there is only one duplicate number, find the duplicate one.
Note:


  1. You must not modify the array (assume the array is read only).
  2. You must use only constant, O(1) extra space.
  3. Your runtime complexity should be less than O(n2).
  4. There is only one duplicate number in the array, but it could be repeated more than once.
-----------------------------------------------------------------------
Sol #1: 因为数字的范围是1 - n, 在范围内取一个值,遍历所给的数组,记下所有比这个值小的个数,进行对比。取值的方法用binary search
O(nlgn)
class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int n = nums.size() - 1;
        int low = 1, high = n;
        
        while (low < high) {
            int mid = (low + high) / 2;
            int count = 0;
            for (int i = 0; i <= n; i++) {
                if (nums[i] <= mid) {
                    count++;
                }
            }
            
            if (count > mid) {
                high = mid;
            }else {
                low = mid + 1;
            }
            if (low == high) return low;
        }
        
    }
};
O(n)
ref:  http://keithschwarz.com/interesting/code/?dir=find-duplicate
class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int n = nums.size();
        int slow = n, fast = n;
        
        while (true) {
            fast = nums[nums[fast - 1] - 1];
            slow = nums[slow - 1];
            if (slow == fast) break;
        }
        
        slow = n;
        while (slow != fast) {
            slow = nums[slow - 1];
            fast = nums[fast - 1];
        }
        
        return slow;
    }
};

Word Pattern
Given a pattern and a string str, find if str follows the same pattern.
Here follow means a full match, such that there is a bijection between a letter in pattern and a non-empty word in str.
Examples:
  1. pattern = "abba", str = "dog cat cat dog" should return true.
  2. pattern = "abba", str = "dog cat cat fish" should return false.
  3. pattern = "aaaa", str = "dog cat cat dog" should return false.
  4. pattern = "abba", str = "dog dog dog dog" should return false.
Notes:
You may assume pattern contains only lowercase letters, and str contains lowercase letters separated by a single space.
--------------------------------------------------
2个hashmap 互相对应
class Solution {
public:
    string getWord(string str, int &index) {
        string rt = "";
        for (; index < str.length(); index++) {
            if (isalpha(str[index])) {
                rt += str[index];
            }else break;
        }
        index++;
        return rt;
    }

    bool wordPattern(string pattern, string str) {
        unordered_map<char,string> pToS;
        unordered_map<string,char> sToP;
        int index = 0;
        
        for (int i = 0; i < pattern.length(); i++) {
            if (index == str.length()) return false;
            string word = getWord(str,index);
            if (pToS.find(pattern[i]) == pToS.end()) {
                pToS[pattern[i]] = word;
            }else if (word != pToS[pattern[i]]) return false;
            
            if (sToP.find(word) == sToP.end()) {
                sToP[word] = pattern[i];
            }else if (sToP[word] != pattern[i]) return false;
        }
        
        return index == str.length() + 1;
    }
};

Word Pattern II
Given a pattern and a string str, find if str follows the same pattern.
Here follow means a full match, such that there is a bijection between a letter in pattern and a non-empty substring in str.
Examples:
  1. pattern = "abab", str = "redblueredblue" should return true.
  2. pattern = "aaaa", str = "asdasdasdasd" should return true.
  3. pattern = "aabb", str = "xyzabcxzyabc" should return false.
Notes:
You may assume both pattern and str contains only lowercase letters.
-------------------------------------------------------
back tracking
对一个pattern[i], 试遍每一种可能
class Solution {
public:
    bool helper(string pattern, int i, string str, int is, unordered_map<char,string> &ptos, unordered_map<string,char> &stop) {
        if (i == pattern.length() && is == str.length()) return true;
        if (i == pattern.length() || is == str.length()) return false;
        
        if (ptos.find(pattern[i]) != ptos.end()) {
            if (ptos[pattern[i]] == str.substr(is,ptos[pattern[i]].length())) {
                return helper(pattern,i + 1, str, is + ptos[pattern[i]].length(),ptos,stop);
            }
            return false;
        }
        
        for (int j = is; j < str.length(); j++) {
            string word = str.substr(is,j - is + 1);
            if (stop.find(word) != stop.end()) continue;
            
            ptos[pattern[i]] = word;
            stop[word] = pattern[i];
            if (helper(pattern, i + 1, str, j + 1, ptos,stop)) return true;
            ptos.erase(pattern[i]);
            stop.erase(word);
        }
        
        return false;
    }

    bool wordPatternMatch(string pattern, string str) {
        unordered_map<char,string> ptos;
        unordered_map<string,char> stop;
        
        return helper(pattern,0,str,0,ptos,stop);
    }
};

Nim Game
 You are playing the following Nim Game with your friend: There is a heap of stones on the table, each time one of you take turns to remove 1 to 3 stones. The one who removes the last stone will be the winner. You will take the first turn to remove the stones.
Both of you are very clever and have optimal strategies for the game. Write a function to determine whether you can win the game given the number of stones in the heap.
For example, if there are 4 stones in the heap, then you will never win the game: no matter 1, 2, or 3 stones you remove, the last stone will always be removed by your friend.
Hint:
  1. If there are 5 stones in the heap, could you figure out a way to remove the stones such that you will always be the winner? 
---------------------------------------
可递归,可DP,但是以下为最简
class Solution {
public:
    bool canWinNim(int n) {
        return n % 4;
    }
};

Best Meeting Point
A group of two or more people wants to meet and minimize the total travel distance. You are given a 2D grid of values 0 or 1, where each 1 marks the home of someone in the group. The distance is calculated using Manhattan Distance, where distance(p1, p2) = |p2.x - p1.x| + |p2.y - p1.y|.
For example, given three people living at (0,0), (0,4), and (2,2):
1 - 0 - 0 - 0 - 1
|   |   |   |   |
0 - 0 - 0 - 0 - 0
|   |   |   |   |
0 - 0 - 1 - 0 - 0
The point (0,2) is an ideal meeting point, as the total travel distance of 2+2+2=6 is minimal. So return 6.
Hint:
  1. Try to solve it in one dimension first. How can this solution apply to the two dimension case?
--------------------------------------------------------------
O(m*n*log(m*n) )
class Solution {
public:
    int minTotalDistance(vector<vector<int>>& grid) {
        int m = grid.size(), n = grid[0].size();
        vector<int> I,J;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == 1) {
                    I.push_back(i);
                    J.push_back(j);
                }
            }
        }
        
        return getDis(I) + getDis(J);
    }
    
    int getDis(vector<int> &num) {
        int rt = 0, left = 0, right = num.size() - 1;
        sort(num.begin(), num.end());
        
        while (left < right) {
            rt += num[right] - num[left];
            right--;
            left++;
        }
        
        return rt;
    }
};

O(mn)
class Solution {
public:
    int minTotalDistance(vector>& grid) {
        int m = grid.size(), n = grid[0].size();
        vector I,J;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == 1) {
                    I.push_back(i);
                }
            }
        }
        
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (grid[j][i] == 1) {
                    J.push_back(i);
                }
            }
        }
        
        return getDis(I) + getDis(J);
    }
    
    int getDis(vector &num) {
        int rt = 0, left = 0, right = num.size() - 1;
        
        while (left < right) {
            rt += num[right] - num[left];
            right--;
            left++;
        }
        
        return rt;
    }
};

Tuesday, October 27, 2015

Day 131, #288 #289 #293 #294 #295 #298 Unique Word Abbreviation, Game of Life, Flip Game, Flip Game II, Find Median from Data Stream, Binary Tree Longest Consecutive Sequence

Unique Word Abbreviation
An abbreviation of a word follows the form <first letter><number><last letter>. Below are some examples of word abbreviations:
a) it                      --> it    (no abbreviation)

     1
b) d|o|g                   --> d1g

              1    1  1
     1---5----0----5--8
c) i|nternationalizatio|n  --> i18n

              1
     1---5----0
d) l|ocalizatio|n          --> l10n
Assume you have a dictionary and given a word, find whether its abbreviation is unique in the dictionary. A word's abbreviation is unique if no other word from the dictionary has the same abbreviation.
Example: 
Given dictionary = [ "deer", "door", "cake", "card" ]

isUnique("dear") -> false
isUnique("cart") -> true
isUnique("cane") -> false
isUnique("make") -> true
-----------------------------------------------------------------
COME_BACK
看清题意
class ValidWordAbbr {
public:
    string getAbre(string s) {
        int len = s.length();
        if (len > 1) {
            s = s[0] + to_string(len - 2) + s[len - 1];
        }
        return s;
    }
    
    ValidWordAbbr(vector<string> &dictionary) {
        for (int i = 0; i < dictionary.size(); i++) {
            string abre = getAbre(dictionary[i]);
            if (dic.find(abre) == dic.end()) {
                vector<string> second;
                second.push_back(dictionary[i]);
                dic[abre] = second;
            }else {
                dic[abre].push_back(dictionary[i]);
            }
        }
    }

    bool isUnique(string word) {
        string abre = getAbre(word);
        if (dic.find(abre) == dic.end()) return true;
        return dic[abre][0] == word && dic[abre].size() == 1;
    }
    
private:
    unordered_map<string,vector<string>> dic;
};


// Your ValidWordAbbr object will be instantiated and called as such:
// ValidWordAbbr vwa(dictionary);
// vwa.isUnique("hello");
// vwa.isUnique("anotherWord");

Game of Life
According to the Wikipedia's article: "The Game of Life, also known simply as Life, is a cellular automaton devised by the British mathematician John Horton Conway in 1970."
Given a board with m by n cells, each cell has an initial state live (1) or dead (0). Each cell interacts with its eight neighbors (horizontal, vertical, diagonal) using the following four rules (taken from the above Wikipedia article):
  1. Any live cell with fewer than two live neighbors dies, as if caused by under-population.
  2. Any live cell with two or three live neighbors lives on to the next generation.
  3. Any live cell with more than three live neighbors dies, as if by over-population..
  4. Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction.
Write a function to compute the next state (after one update) of the board given its current state.
Follow up: 
  1. Could you solve it in-place? Remember that the board needs to be updated at the same time: You cannot update some cells first and then use their updated values to update other cells.
  2. In this question, we represent the board using a 2D array. In principle, the board is infinite, which would cause problems when the active area encroaches the border of the array. How would you address these problems?
---------------------------------------------------------------------
额外空间
class Solution {
public:
    vector<int> row;
    vector<int> col; 
    bool isLive(int i, int j, int m, int n, vector<vector<int>>& board) {
        if (i < 0 || j < 0 || i == m || j == n) return false;
        return board[i][j];
    }

    void gameOfLife(vector<vector<int>>& board) {
        int m = board.size();
        int n = board[0].size();
        vector<vector<int>> rt(m, vector<int>(n));
        row = {-1,-1,-1,0,0,1,1,1};
        col = {-1,0,1,-1,1,-1,0,1};
        
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                int numOfLives = 0;
                for (int k = 0; k < 8; k++) {
                    if (isLive(row[k] + i,col[k] + j, m, n, board)) {
                        numOfLives++;
                    }
                }
                
                if (numOfLives < 2 || numOfLives > 3) rt[i][j] = 0;
                else if (board[i][j] && numOfLives <= 3) rt[i][j] = 1;
                else if (numOfLives == 3) rt[i][j] = 1;
            }
        }
        board = rt;
    }
};

constant space
用-1来表示之前为0,现在为1. -2来表示之前为1,现在为0
0 -> -1 -> 1
1 -> -2 -> 0
class Solution {
public:
    vector<int> row;
    vector<int> col; 
    bool isLive(int i, int j, int m, int n, vector<vector<int>>& board) {
        if (i < 0 || j < 0 || i == m || j == n) return false;
        if (board[i][j] == 0 || board[i][j] == -1) return false; 
        return true;
    }

    void gameOfLife(vector<vector<int>>& board) {
        int m = board.size();
        int n = board[0].size();
        row = {-1,-1,-1,0,0,1,1,1};
        col = {-1,0,1,-1,1,-1,0,1};
        
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                int numOfLives = 0;
                for (int k = 0; k < 8; k++) {
                    if (isLive(row[k] + i,col[k] + j, m, n, board)) {
                        numOfLives++;
                    }
                }
                
                if (board[i][j] && numOfLives < 2) board[i][j] = -2;
                else if (board[i][j] && (numOfLives == 3 || numOfLives == 2)) continue;
                else if (board[i][j] && numOfLives > 3) board[i][j] = -2;
                else if (numOfLives == 3) board[i][j] = -1;
            }
        }
        
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (board[i][j] == -1) board[i][j] = 1;
                if (board[i][j] == -2) board[i][j] = 0;
            }
        }
    }
};

Flip Game
You are playing the following Flip Game with your friend: Given a string that contains only these two characters: + and -, you and your friend take turns to flip twoconsecutive "++" into "--". The game ends when a person can no longer make a move and therefore the other person will be the winner.
Write a function to compute all possible states of the string after one valid move.
For example, given s = "++++", after one move, it may become one of the following states:
[
  "--++",
  "+--+",
  "++--"
]
If there is no valid move, return an empty list [].
---------------------------------------------
class Solution {
public:
    vector<string> generatePossibleNextMoves(string s) {
        vector<string> rt;
        for (int i = 1; i < s.length(); i++) {
            if (s[i] == '+' && s[i - 1] == '+') {
                s[i] = '-';
                s[i - 1] = '-';
                rt.push_back(s);
                s[i] = '+';
                s[i - 1] = '+';
            }
        }
        
        return rt;
    }
};

Flip Game II
You are playing the following Flip Game with your friend: Given a string that contains only these two characters: + and -, you and your friend take turns to flip twoconsecutive "++" into "--". The game ends when a person can no longer make a move and therefore the other person will be the winner.
Write a function to determine if the starting player can guarantee a win.
For example, given s = "++++", return true. The starting player can guarantee a win by flipping the middle "++" to become "+--+".
Follow up:
Derive your algorithm's runtime complexity.
--------------------------------------------------------------
递归
T(n) = n * T(n - 1)
        = n * (n - 1) * T(n - 2)
        = n * (n - 1) * (n - 2) * T(n - 3)
        ...
        = n!
class Solution {
public:
    bool canWin(string s) {
        for (int i = 1; i < s.length(); i++) {
            if (s[i] == '+' && s[i - 1] == '+') {
                s[i] = '-';
                s[i - 1] = '-';
                if (!canWin(s)) return true;
                s[i] = '+';
                s[i - 1] = '+';
            }
        }
        
        return false;
    }
};
COME_BACK
game theory的方法可以达到O(n^2)

Find Median from Data Stream
Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle value.
Examples: 
[2,3,4] , the median is 3
[2,3], the median is (2 + 3) / 2 = 2.5
Design a data structure that supports the following two operations:
  • void addNum(int num) - Add a integer number from the data stream to the data structure.
  • double findMedian() - Return the median of all elements so far.
For example:
add(1)
add(2)
findMedian() -> 1.5
add(3) 
findMedian() -> 2
---------------------------------------------------------------------------
2个queue,还有其他方法吗
一个TreeSet加2个指针,跟2个heap原理是一样的
class MedianFinder {
public:
    struct cmp {
        bool operator() (int i1, int i2) {
            return i1 > i2;
        }
    };
    
    // Adds a number into the data structure.
    void addNum(int num) {
        small.push(num);
        int temp = small.top();
        small.pop();
        large.push(temp);
        temp = large.top();
        large.pop();
        if (small.size() > large.size()) {
            large.push(temp);
        }else {
            small.push(temp);
        }
    }

    // Returns the median of current data stream
    double findMedian() {
        if ((small.size() + large.size()) % 2 == 0) {
            return (small.top() + large.top()) / 2.0;
        }else {
            return small.top();
        }
    }

private:
    priority_queue<int> small;
    priority_queue<int,vector<int>,cmp> large;
};

// Your MedianFinder object will be instantiated and called as such:
// MedianFinder mf;
// mf.addNum(1);
// mf.findMedian();

Binary Tree Longest Consecutive Sequence
Given a binary tree, find the length of the longest consecutive sequence path.
The path refers to any sequence of nodes from some starting node to any node in the tree along the parent-child connections. The longest consecutive path need to be from parent to child (cannot be the reverse).
For example,
   1
    \
     3
    / \
   2   4
        \
         5
Longest consecutive sequence path is 3-4-5, so return 3.
   2
    \
     3
    / 
   2    
  / 
 1
Longest consecutive sequence path is 2-3,not3-2-1, so return 2.
-------------------------------------------------------
/**
 * 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 dfs(TreeNode* root, int cur, int &maxL, int target) {
        if (root == NULL) return;
        if (root->val == target) {
            cur++;
        }else {
            cur = 1;
        }
        maxL = max(maxL,cur);
        dfs(root->left, cur, maxL, root->val + 1);
        dfs(root->right, cur, maxL, root->val + 1);
    }

    int longestConsecutive(TreeNode* root) {
        int maxL = 0;
        if (root == NULL) return 0;
        dfs(root,0,maxL,root->val);
        return maxL;
    }
};

Friday, October 16, 2015

Google interview questions #8

ref: http://www.mitbbs.com/article_t/JobHunting/33072599.html

是烙印, 问的是LCA of DAG. 全程不让写代码, 就一直问follow up, 问复杂度, 问怎
么做, 为什么要这么做, 用那个为什么不好, 后来问要是有很多pair of nodes 求LCA
要怎么做preprocessing.

解法:
2个node各做bfs,记录走过的node和距离,如果出现重复就记录2个的距离和,直到找到最小的距离和

follow up:
预先计算出每个node到其他所有node的距离。当给定2个node时,找出所有的共同点,计算距离和

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

x_0 = C (integer)
if x_n is even then x_{n+1} is x_n / 2
if x_n is odd then x_{n+1} to be 3 * x_n + 1

这题的复杂度是O(logC)吗?

https://en.wikipedia.org/wiki/Collatz_conjecture

---------------------------------------------------------------------
ref: http://www.meetqun.com/forum.php?mod=viewthread&tid=11377&extra=page%3D1%26filter%3Dtypeid%26typeid%3D50

一队人,每一个人有两个值(height,tvalue),其中height代表身高,tvalue代表这个人前面有多少人比他高。现在把这个array of (height, tvalue)打乱,然后要还原这个数列。.

解法:
按height排序,从最低height开始,tvalue就是它在新array里的最终位置。需要注意是,每次都要对之前index前面里已经有多少被放置

最终的index = tvalue + (index之前已经确定的元素个数)

所以复杂度是O(n ^ 2)

nlogn 的解法:根据array的index建立一个bst,附带一个额外的值代表此subtree当前有多少个node被填过

-------------------------------------------------------------------------------------
ref: http://www.meetqun.com/forum.php?mod=viewthread&tid=7849&extra=page%3D1%26filter%3Dtypeid%26typeid%3D50

#1 把bst变成双向链表
解法:inorder遍历,保证一个pointer pass by reference

逆序数
解法: divide and conquer(merge sort)

#2 实现Candy Crush
1.m行n列的矩阵;2.q种花色物品;3.矩阵里每个cell的花色都是random的;4.初始化之后至少一个available的move;5.no 3-run,即初始化的时候不能直接出现三个同种物品连一线的情况。
好像还有其他几个要求,我已经记不清了。
我就开始按照他的要求挨个进行分析。先是random函数,然后就可以用双层for循环来填充每一个cell。我说但是一个available的move这个太难了,因为有太多的情况。就问他要提示,而且我不断做尝试。他说“其实答案比你想想的简单多了。最后直接告诉我:“你可以直接在填充所有的cell之前先创造一个可以move的三个物品先放进去。我恍然大悟,对对对,在双层for循环之前先做这一步操作。
下一个是"no 3-run的条件”。我说就每当在填充一个之前先往上下左右四个方向的两个格子都跟将random生成的物品进行比对。他说:“其实另一种情况。”我说:“就是将要填充的物品正好在两个同色物品之间。”他说对。我说咱们就可以用一个while循环,如果random生成的颜色不符合要求(设置一个boolean函数来判断,这里不要求实现)就继续循环。; u# V. Y: \ p7 B$ {/ a/ [: n
他说:“OK。其实这样会stuck到一种情况,你来想想。”我就想到比如比如当前方格的上、下、左、右各有一种两个同色物品排列,那么这个cell填这四种颜色的任何一种都不对了。”他说对,怎么避免呢?经过他的提示我就写这样的情况下直接清除board中所有已填颜色从头来过。0 L% F- Z) k( F
难点解决了,下一步就是写代码了,然后照相。
感觉这种题目面试官已经在里面设置好了处理的难点来等待你遇到和解决,然后看你尝试解决问题的方法以及交流能力。就像寻宝一样不断地试探、前进、解决问题。
#3 Tries

#4
比如1729 = 1^3 + 12 ^ 3 = 9 ^ 3 + 10 ^ 3。像这种可以由两对或两对以上的立方和组成的数叫做R某某某数(单词记不清了)。让你构造一个函数,输入是N,输出小于N的所有这种数。/ u" f% G( Z( |9 Q0 f- _1 H5 K
其实方法很简单,就是将从1到N的立方根之间的数,从中任取两个来求立方和,然后看结果集当中有没有出现两次或两次以上的数。就是类似于暴力了。

解法: 暴力 + hash,从1开始算到N

----------------------------------------------------------
ref: http://www.meetqun.com/forum.php?mod=viewthread&tid=11067&extra=page%3D1%26filter%3Dtypeid%26typeid%3D50

Google onsite
1. 类似这道题:
给如下的数据格式:<start_time, end_time, value>
For example,
1, 3, 100
2, 4, 200
5, 6, 300
。。。
这些数据时间点可能有重合。在时间段2~3之间,value的和是100+200 = 300. 找出这
组数据中最高的value和
[consider end points]

解法:类似meeting room,把开始、结束时间排序,设2个指针p1, p2。
如果是开始时间,cur + value[p1++], 结束时间cur - value[p2++]

2.find k most frequent words from a file
解法:priority queue + hash map

3.brainstorming: 一个上传文件的service,之前正常运转,突然有一天挂了,这期间
没改代码。问怎么排查问题。

查log,物理硬件

-------------------------------------------------------------------------------
ref: http://www.meetqun.com/forum.php?mod=viewthread&tid=301&extra=page%3D1%26filter%3Dtypeid%26typeid%3D50&page=6

check一个数是否是3的次幂


遍历
查表,32位内3的幂也就几十位
2分

---------------------------------------------------------------------------------
ref: http://www.geeksforgeeks.org/dynamic-programming-set-18-word-wrap/
word wrap

解法:
标准dp
 int cube(int num) {
 return  num * num * num;
}

int minCost(vector<int> &v,vector<int> &dp,int index, int width) {
 if (index == v.size()) return 0;
 if (dp[index] != INT_MAX) return dp[index];
 int len = v[index];
 int minC = INT_MAX;
 for (int i = index; i < v.size(); i++) {
  minC = min(minC, cube(width - len) + minCost(v,dp,i + 1,width));
  len += v[i] + 1;
  if (width < len) break;
 }
 dp[index] = minC;
 return minC;
}

int spawn(vector<int> &v, int width) {
 vector<int> dp(v.size(),INT_MAX);
 return minCost(v,dp,0,width);
}

---------------------------------------
round 1: 给定一个class
class Event {
int id; /nsor id
int timestamp;
boolean status;
}
意思是某个sensor会触发一个事件使其状态status改变,true->false or false->true. 设计数据结构,存储以下信息:每个事件的sensor id, timestamp和status,使其可以响应一种query, query包含id, timestamp,返回这个id在这个时刻的status
follow up: 如果来的event不是按照timestamp递增的,怎么修改数据结构

round 2:
一个二维矩阵,里面是bits (1 or 0),可以用int 或byte表示,左右翻转这个矩阵,有什么优化

round 3:
一个猜词游戏,给定一个词典,里面的词的长度都一样,有一个secret word在这个词典里,每次从词典里选一个词猜,只会返回和secret word有几个字母是一样的(只知道数量,不知道位置)。问怎样猜能尽量减少猜测次数

Saturday, October 3, 2015

Palantir interview question #1

--------------------------------------------------------------------
ref : https://shawnlincoding.wordpress.com/2015/03/16/palantir%E9%9D%A2%E7%BB%8F/
1,
1. 给你一个棋盘 int[][] board, 你可以交换任何一个棋子和它的邻居(横向或者竖向相邻的棋子),如果交换后,在横向或者竖向产生了大于等于三个连续的一样的棋子 e.g. 4 4 4
5
5
5
那么就算交换有效。(就是一个比较常见的游戏,忘记叫啥名字了)
请你写一个函数返回所有可以有效交换的棋子的坐标对。 比如 ((0, 0), (1, 0)) , ((3,2),(3,3)).

2,看code,debug, 然后写出正确的code,这个没啥说的

3 Merge interval
Running Median : follow up: O(1) space


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

write a fuction to titlecase a string
for example
input: the quick brown fox
output: The Quick Brown Fox
two pointers, remember to update flag


DFS,很像coursera普林算法课讲得CC, 看看所以0是不是在一个CC里面
从0,0开始做一次DFS,如果有0没被marked到那就是invalid的



Friday, September 25, 2015

Day 130, #282 #286 Expression Add Operators, Walls and Gates

Expression Add Operators
Given a string that contains only digits 0-9 and a target value, return all possibilities to add binary operators (not unary) +, -, or * between the digits so they evaluate to the target value.
Examples: 
"123", 6 -> ["1+2+3", "1*2*3"] 
"232", 8 -> ["2*3+2", "2+3*2"]
"105", 5 -> ["1*0+5","10-5"]
"00", 0 -> ["0+0", "0-0", "0*0"]
"3456237490", 9191 -> []
---------------------------------------------------------------------------
COME_BACK
#1 这种for循环内的写法可以简化没有符合时的情况
如1234
1 _ 234
12_34
123_4
1234
-----------
from 1_234:
1_2_34
1_23_4
1_234
........

如果遇到“*”,则返回之前的操作(因为之前的运算符和值都已经存好)
1 + 2 * 3,之前 1 + 2已经算出为3,之前的运算符为+,值为2。然后此时 总值- 2 + 2 * 3
cur为当前的总值,op为之前运算符,val为上一步计算的值

class Solution {
public:
    int target;
    void dfs(vector<string> &rt,string num,int index,string sofar,long cur,string op,long val) {
        if (index == num.length() && target == cur) {
            rt.push_back(sofar);
        }
        
        for (int i = index; i < num.length(); i++) {
            string s = num.substr(index,i + 1 - index);
            if (s != to_string(stol(s))) continue;
            int now = stol(s);
            dfs(rt,num,i + 1,sofar + "+" + s,cur + now,"+",now);
            dfs(rt,num,i + 1,sofar + "-" + s,cur - now,"-",now);
            if (op == "-") {
                dfs(rt,num,i + 1,sofar + "*" + s,cur + val - val * now,op,val * now);
            }else if (op == "+") {
                dfs(rt,num,i + 1,sofar + "*" + s,cur - val + val * now,op,val * now);
            }else {
                dfs(rt,num,i + 1,sofar + "*" + s,val * now,op,val * now);
            }
        }
    }

    vector<string> addOperators(string num, int target) {
        vector<string> rt;
        this->target = target;
        
        for (int i = 1; i <= num.length(); i++) {
            string s = num.substr(0,i);
            if (s != to_string(stol(s))) continue;
            dfs(rt,num,i,s,stol(s),"",stol(s));
        }
        
        return rt;
    }
};

Walls and Gates
You are given a m x n 2D grid initialized with these three possible values.
  1. -1 - A wall or an obstacle.
  2. 0 - A gate.
  3. INF - Infinity means an empty room. We use the value 231 - 1 = 2147483647 to represent INF as you may assume that the distance to a gate is less than2147483647.
Fill each empty room with the distance to its nearest gate. If it is impossible to reach a gate, it should be filled with INF.
For example, given the 2D grid:
INF  -1  0  INF
INF INF INF  -1
INF  -1 INF  -1
  0  -1 INF INF
After running your function, the 2D grid should be:
  3  -1   0   1
  2   2   1  -1
  1  -1   2  -1
  0  -1   3   4
------------------------------------------------------------------------
找出所有的gate,然后同时bfs

class Solution {
public:
    void wallsAndGates(vector<vector<int>>& rooms) {
        int m = rooms.size();
        if (m == 0) return;
        int n = rooms[0].size();
        queue<pair<int,int>> que;
        
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (rooms[i][j] == 0) {
                    que.push(make_pair(i,j));
                }
            }
        }
        
        int size = que.size();
        int dis = 1;
        while (!que.empty()) {
            int row = que.front().first;
            int col = que.front().second;
            size--;
            que.pop();
           
            if (row + 1 < m && rooms[row + 1][col] > dis) {
                rooms[row + 1][col] = dis;
                que.push(make_pair(row + 1,col));
            }
            if (row - 1 >= 0 && rooms[row - 1][col] > dis) {
                rooms[row - 1][col] = dis;
                que.push(make_pair(row - 1,col));
            }
            if (col + 1 < n && rooms[row][col + 1] > dis) {
                rooms[row][col + 1] = dis;
                que.push(make_pair(row,col + 1));
            }
            if (col - 1 >= 0 && rooms[row][col - 1] > dis) {
                rooms[row][col - 1] = dis;
                que.push(make_pair(row,col - 1));
            }
            
            if (size == 0) {
                size = que.size();
                dis++;
            }
        }
    }
};

Tuesday, September 22, 2015

Day 129, #277 #278 #281 #283 #284 #285 Find the Celebrity, First Bad Version, Zigzag Iterator, Move Zeroes, Peeking Iterator, Inorder Successor in BST

Find the Celebrity
Suppose you are at a party with n people (labeled from 0 to n - 1) and among them, there may exist one celebrity. The definition of a celebrity is that all the other n - 1people know him/her but he/she does not know any of them.
Now you want to find out who the celebrity is or verify that there is not one. The only thing you are allowed to do is to ask questions like: "Hi, A. Do you know B?" to get information of whether A knows B. You need to find out the celebrity (or verify there is not one) by asking as few questions as possible (in the asymptotic sense).
You are given a helper function bool knows(a, b) which tells you whether A knows B. Implement a function int findCelebrity(n), your function should minimize the number of calls to knows.
Note: There will be exactly one celebrity if he/she is in the party. Return the celebrity's label if there is a celebrity in the party. If there is no celebrity, return -1.
-------------------------------------------------------------------
COME_BACK
对a做检测,如果a认识b || b不认识a,a就不会是celebrity
// Forward declaration of the knows API.
bool knows(int a, int b);

class Solution {
public:
    int findCelebrity(int n) {
        for (int a = 0; a < n; a++) {
            int b = 0;
            for (; b < n; b++) {
                if (a == b) continue;
                if (knows(a,b) || !knows(b,a)) {
                    break;
                }
            }
            if (b == n) return a;
        }
        
        return -1;
    }
};
第一个循坏对can进行挑选,如果i不认识can,则说明can一定不是celebrity。如果i认识can,能说明i一定不是celebrity
// Forward declaration of the knows API.
bool knows(int a, int b);

class Solution {
public:
    int findCelebrity(int n) {
        int can = 0;
        for (int i = 1; i < n; i++) {
            if (!knows(i,can)) {
                can = i;
            }
        }
        
        for (int i = 0; i < n; i++) {
            if (i == can) continue;
            if (!knows(i,can) || knows(can,i)) return -1;
        }
        
        return can;
    }
};

Java, 关键:
1. 所有人都认识celebrity(第二个for循环),如果谁不被人认识,那他就不是celebrity( 第一个for循环)
2. celebrity谁也不认识(第二个for循环)
/* The knows API is defined in the parent class Relation.
      boolean knows(int a, int b); */

public class Solution extends Relation {
    public int findCelebrity(int n) {
        int cand = 0;
        
        for (int i = 1; i < n; i++) {
            if (knows(cand, i)) {
                cand = i;
            }
        }
        
        for (int i = 0; i < n; i++) {
            if ((cand != i && knows(cand, i)) || !knows(i, cand)) return -1;
        }
        
        return cand;
    }
}

First Bad Version
You are a product manager and currently leading a team to develop a new product. Unfortunately, the latest version of your product fails the quality check. Since each version is developed based on the previous version, all the versions after a bad version are also bad.
Suppose you have n versions [1, 2, ..., n] and you want to find out the first bad one, which causes all the following ones to be bad.
You are given an API bool isBadVersion(version) which will return whether version is bad. Implement a function to find the first bad version. You should minimize the number of calls to the API.
Credits:
Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases.
------------------------------------------------------
Binary search
// Forward declaration of isBadVersion API.
bool isBadVersion(int version);

class Solution {
public:
    int firstBadVersion(int n) {
        int left = 1, right = n;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            bool bad = isBadVersion(mid);
            if (bad && (mid == 1 || !isBadVersion(mid - 1))) return mid;
            if (bad) {
                right = mid - 1;
            }else {
                left = mid + 1;
            }
        }
        
        return -1;
    }
};

Java, recursion
/* The isBadVersion API is defined in the parent class VersionControl.
      boolean isBadVersion(int version); */

public class Solution extends VersionControl {
    public int firstBadVersion(int n) {
        return rec(1, n);
    }
    
    private int rec(int left, int right) {
        if (left > right) return left;
        int mid = left + (right - left) / 2;
        boolean isBad = isBadVersion(mid);
        if (!isBad && isBadVersion(mid + 1)) {
            return mid + 1;
        }
        
        if (isBad) {
            return rec(left, mid - 1);
        }
        
        return rec(mid + 1, right);
    }
}

Zigzag Iterator
Given two 1d vectors, implement an iterator to return their elements alternately.
For example, given two 1d vectors:
v1 = [1, 2]
v2 = [3, 4, 5, 6]
By calling next repeatedly until hasNext returns false, the order of elements returned by next should be: [1, 3, 2, 4, 5, 6].
Follow up: What if you are given k 1d vectors? How well can your code be extended to such cases?
Clarification for the follow up question - Update (2015-09-18):
The "Zigzag" order is not clearly defined and is ambiguous for k > 2 cases. If "Zigzag" does not look right to you, replace "Zigzag" with "Cyclic". For example, given the following input:
[1,2,3]
[4,5,6,7]
[8,9]
It should return [1,4,8,2,5,9,3,6,7].
-------------------------------------------------------------
适用于k个
http://shibaili.blogspot.com/2015/08/notes-from-others.html
class ZigzagIterator {
public:
    ZigzagIterator(vector<int>& v1, vector<int>& v2) {
        v.push_back(v1);
        v.push_back(v2);
        zig = 0;
        itrs = vector<int>(v.size(),0);
    }

    int next() {
        hasNext();
        int rt = v[zig][itrs[zig]];
        itrs[zig]++;
        zig = (zig + 1) % v.size();
        return rt;
    }

    bool hasNext() {
        for (int i = 0; i < v.size(); i++) {
            if (itrs[zig] >= v[zig].size()) {
                zig = (zig + 1) % v.size();
            }else {
                return true;
            }
        }
        return false;
    }
private:
    vector<vector<int>> v;
    vector<int> itrs;
    int zig = 0;
};

/**
 * Your ZigzagIterator object will be instantiated and called as such:
 * ZigzagIterator i(v1, v2);
 * while (i.hasNext()) cout << i.next();
 */

Move Zeroes
Given an array nums, write a function to move all 0's to the end of it while maintaining the relative order of the non-zero elements.
For example, given nums = [0, 1, 0, 3, 12], after calling your function, nums should be [1, 3, 12, 0, 0].
Note:
  1. You must do this in-place without making a copy of the array.
  2. Minimize the total number of operations.

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

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int zero = 0;
        for (int i = 0; i < nums.size(); i++) {
            if (nums[i] != 0) {
                swap(nums[i],nums[zero]);
                zero++;
            }
        }
    }
};

Peeking Iterator
Given an Iterator class interface with methods: next() and hasNext(), design and implement a PeekingIterator that support the peek() operation -- it essentially peek() at the element that will be returned by the next call to next().

Here is an example. Assume that the iterator is initialized to the beginning of the list: [1, 2, 3].
Call next() gets you 1, the first element in the list.
Now you call peek() and it returns 2, the next element. Calling next() after that still return 2.
You call next() the final time and it returns 3, the last element. Calling hasNext() after that should return false.
Hint:
  1. Think of "looking ahead". You want to cache the next element.
  2. Is one variable sufficient? Why or why not?
  3. Test your design with call order of peek() before next() vs next() before peek().
  4. For a clean implementation, check out Google's guava library source code.
Follow up: How would you extend your design to be generic and work with all types, not just integer?
--------------------------------------------------------------------
// Below is the interface for Iterator, which is already defined for you.
// **DO NOT** modify the interface for Iterator.
class Iterator {
    struct Data;
 Data* data;
public:
 Iterator(const vector<int>& nums);
 Iterator(const Iterator& iter);
 virtual ~Iterator();
 // Returns the next element in the iteration.
 int next();
 // Returns true if the iteration has more elements.
 bool hasNext() const;
};


class PeekingIterator : public Iterator {
public:
 PeekingIterator(const vector<int>& nums) : Iterator(nums) {
     // Initialize any member here.
     // **DO NOT** save a copy of nums and manipulate it directly.
     // You should only use the Iterator interface methods.
 }

    // Returns the next element in the iteration without advancing the iterator.
 int peek() {
        if (st.empty()) {
         st.push(Iterator::next());
     }
     return st.top();
 }

 // hasNext() and next() should behave the same as in the Iterator interface.
 // Override them if needed.
 int next() {
     if (st.empty()) return Iterator::next();
     int rt = st.top();
     st.pop();
     return rt;
 }

 bool hasNext() const {
     return !st.empty() || Iterator::hasNext();
 }
private:
    stack<int> st;
};

In Java
// Java Iterator interface reference:
// https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html
class PeekingIterator implements Iterator<Integer> {

    private Iterator<Integer> itr;
    private Integer next;
	public PeekingIterator(Iterator<Integer> iterator) {
	    // initialize any member here.
	    itr = iterator;
        next = itr.hasNext() ? itr.next() : null;
	}

    // Returns the next element in the iteration without advancing the iterator.
	public Integer peek() {
        return next;
	}

	// hasNext() and next() should behave the same as in the Iterator interface.
	// Override them if needed.
	@Override
	public Integer next() {
	    
        Integer rt = next;
        next = itr.hasNext() ? itr.next() : null;
        return rt;
	}

	@Override
	public boolean hasNext() {
	    return next != null;
	}
}


Inorder Successor in BST
Given a binary search tree and a node in it, find the in-order successor of that node in the BST.
Note: If the given node has no in-order successor in the tree, return null.
------------------------------------------------
遍历
/**
 * 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 *mostLeft(TreeNode *root) {
        while (root->left != NULL) {
            root = root->left;
        }
        return root;
    }

    TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {
        if (p->right != NULL) {
            return mostLeft(p->right);
        }
        
        TreeNode *suc = NULL;
        while (root != NULL) {
            if (root->val > p->val) {
                suc = root;
                root = root->left;
            }else {
                root = root->right;
            }
        }
        return suc;
    }
};

递归
/**
 * 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* inorderSuccessor(TreeNode* root, TreeNode* p) {
        if (root == NULL) {
            return root;
        }
        if (root->val <= p->val) {
            return inorderSuccessor(root->right,p);
        }
        TreeNode *next = inorderSuccessor(root->left,p);
        if (next == NULL) return root;
        return next;
    }
};

Sunday, September 20, 2015

Day 128, #256 #265 #267 #273 Paint House, Paint House II, Palindrome Permutation II, Integer to English Words

Paint House
There are a row of n houses, each house can be painted with one of the three colors: red, blue or green. The cost of painting each house with a certain color is different. You have to paint all the houses such that no two adjacent houses have the same color.
The cost of painting each house with a certain color is represented by a n x 3 cost matrix. For example, costs[0][0] is the cost of painting house 0 with color red;costs[1][2] is the cost of painting house 1 with color green, and so on... Find the minimum cost to paint all houses.
Note:
All costs are positive integers.
-----------------------------------------
方程式:
递归:超时,可加memoization
class Solution {
public:
    int helper(vector<vector<int>>& costs, int index,int pre) {
        if (index == costs.size()) return 0;
        int min1 = INT_MAX,min2 = INT_MAX,min3 = INT_MAX;
        if (pre != 0) {
            min1 = costs[index][0] + helper(costs,index + 1,0);
        }
        if (pre != 1) {
            min2 = costs[index][1] + helper(costs,index + 1,1);
        }
        if (pre != 2) {
            min3 = costs[index][2] + helper(costs,index + 1,2);
        }
        
        return min(min(min2,min1),min3);
    }

    int minCost(vector<vector<int>>& costs) {
        return helper(costs,0,-1);
    }
};

DP:
3个array,dp[k][i] = 为在第i个房子涂k的颜色所需要的总花费
dp[0][i] = costs[i][0] + min(dp[1][i - 1],dp[2][i - 1]);
其他2个颜色类同

以下方法已经做过空间优化
class Solution {
public:
    int minCost(vector<vector<int>>& costs) {
        int n = costs.size();
        if (n == 0) return 0;
        int dp0 = costs[0][0];
        int dp1 = costs[0][1];
        int dp2 = costs[0][2];
        
        for (int i = 1; i < n; i++) {
            int t0 = dp0, t1 = dp1, t2 = dp2;
            dp0 = costs[i][0] + min(t1,t2);
            dp1 = costs[i][1] + min(t2,t0);
            dp2 = costs[i][2] + min(t1,t0);
        }

        return min(min(dp0,dp1),dp2);
    }
};

Paint House II
There are a row of n houses, each house can be painted with one of the k colors. The cost of painting each house with a certain color is different. You have to paint all the houses such that no two adjacent houses have the same color.
The cost of painting each house with a certain color is represented by a n x k cost matrix. For example, costs[0][0] is the cost of painting house 0 with color 0; costs[1][2] is the cost of painting house 1 with color 2, and so on... Find the minimum cost to paint all houses.
Note:
All costs are positive integers.
Follow up:
Could you solve it in O(nk) runtime?
------------------------------------------
2个variable保存上一次涂房子的最小的2个值,first是值,second是颜色

class Solution {
public:
    int minCostII(vector>& costs) {
        int n = costs.size();
        if (n == 0) return 0;
        int k = costs[0].size();
        vector dp = costs[0];
        int minCost = INT_MAX;
        
        for (int i = 1; i < n; i++) {
            // pair of cost - color
            pair min1 = make_pair(INT_MAX,-1);
            pair min2 = make_pair(INT_MAX,-1);
            // find the smallest two values from previous painting job
            for (int j = 0; j < k; j++) {
                if (dp[j] < min1.first) {
                    min2 = min1;
                    min1.first = dp[j];
                    min1.second = j;
                }else if (dp[j] < min2.first) {
                    min2.first = dp[j];
                    min2.second = j;
                }
            }
            
            for (int j = 0; j < k; j++) {
                if (j == min1.second) {
                    dp[j] = costs[i][j] + min2.first;
                }else {
                    dp[j] = costs[i][j] + min1.first;
                }
            }
        }
    
        for (int i = 0; i < k; i++) {
            minCost = min(minCost,dp[i]);
        }
        
        return minCost;
    }
};

Palindrome Permutation II
 Given a string s, return all the palindromic permutations (without duplicates) of it. Return an empty list if no palindromic permutation could be form.
For example:
Given s = "aabb", return ["abba", "baab"].
Given s = "abc", return [].
Hint:

  1. If a palindromic permutation exists, we just need to generate the first half of the string.
  2. To generate all distinct permutations of a (half of) string, use a similar approach from: Permutations II or Next Permutation.
------------------------------
#1 检测所给string是否可生成pal, 跟I一样
#2 典型permutation
class Solution {
public:
    vector<int> collect(string s,string &single) {
        vector<int> count(256,0);
        for (int i = 0; i < s.length(); i++) {
            count[s[i]]++;
        }
        
        for (int i = 0; i < 256; i++) {
            if (count[i] % 2 == 1) {
                if (single == "") {
                    single += i;
                }else {
                    vector<int> t;
                    return t;
                }
            }
        }
        
        return count;
    }

    void rec(vector<string> &rt,vector<int> &count,string s,int total,string single) {
        if (total == 0) {
            string t = s;
            reverse(t.begin(),t.end());
            rt.push_back(s + single + t);
            return;
        }
        
        for (int i = 0; i < 256; i++) {
            if (count[i] < 2) continue;
            string t = s;
            t += i;
            count[i] -= 2;
            rec(rt,count,t,total - 1,single);
            count[i] += 2;
        }
    }

    vector<string> generatePalindromes(string s) {
        vector<string> rt;
        string single = "";
        vector<int> count = collect(s,single);
        if (count.size() == 0) return rt;
        rec(rt,count,"",s.length() / 2,single);
        return rt;
    }
};

Java
class Solution {
    public List<String> generatePalindromes(String s) {
        List<String> rt = new ArrayList<>();
        int[] map = new int[128];
        int odd = 0;
        
        for (int i = 0; i < s.length(); i++) {
            map[s.charAt(i)] += 1;
            if (map[s.charAt(i)] % 2 == 1) odd++;
            else odd--;
        }
        
        if (odd > 1) return rt;
        
        String mid = "";
        for (int i = 0; i < 128; i++) {
            if (map[i] % 2 == 1) mid += (char)i;
        }

        perm(rt, "", s.length() / 2, mid, map);
        
        return rt;
    }
    
    private void perm(List<String> rt, String curS, int total, String mid, int[] map) {
        if (total == 0) {
            rt.add(curS + mid + new StringBuilder(curS).reverse().toString());
            return;
        }
        
        for (int i = 0; i < 128; i++) {
            if (map[i] < 2) continue;
            map[i] -= 2;
            perm(rt, curS + (char)i, total - 1, mid, map);
            map[i] += 2;
        }
    }
}
Integer to English Words
Convert a non-negative integer to its english words representation. Given input is guaranteed to be less than 231 - 1.
For example,
123 -> "One Hundred Twenty Three"
12345 -> "Twelve Thousand Three Hundred Forty Five"
1234567 -> "One Million Two Hundred Thirty Four Thousand Five Hundred Sixty Seven"
Hint:
  1. Did you see a pattern in dividing the number into chunk of words? For example, 123 and 123000.
  2. Group the number by thousands (3 digits). You can write a helper function that takes a number less than 1000 and convert just that chunk to words.
  3. There are many edge cases. What are some good test cases? Does your code work with input such as 0? Or 1000010? (middle chunk is zero and should not be printed out)
----------------------------------------------------------------
注意空格
class Solution {
public:
    string translate(vector<string> &ones,vector<string> &oneTens,vector<string> &tens,vector<string> &ends,int nums,string end) {
        string rt = "";
        if (nums >= 100) {
            rt += ones[nums / 100 - 1] + " Hundred";
            nums %= 100;
        }
        
        if (nums >= 10) {
            if (rt != "") rt += " ";
            if (nums <= 19) {
                rt += oneTens[nums % 10];
                return rt + end;
            }
            rt += tens[nums / 10 - 2];
            nums %= 10;
        }
        
        if (nums >= 1) {
            if (rt != "") rt += " ";
            rt += ones[nums - 1];
        }
        
        return rt + end;
    }


    string numberToWords(int num) {
        if (num == 0) return "Zero";
        vector<string> ones = {"One","Two","Three","Four","Five","Six","Seven","Eight","Nine"};
        vector<string> oneTens = {"Ten","Eleven","Twelve","Thirteen","Fourteen","Fifteen","Sixteen","Seventeen","Eighteen","Nineteen"};
        vector<string> tens = {"Twenty","Thirty","Forty","Fifty","Sixty","Seventy","Eighty","Ninety"};
        vector<string> ends = {" Billion"," Million"," Thousand",""};
        
        string rt = "";
        int temp = 0, endI = 0,bill = 1000000000;
        while (num > 0) {
            if (num / bill > 0) {
                if (rt != "") rt += " ";
                rt += translate(ones,oneTens,tens,ends,num / bill,ends[endI]);
            }
            num %= bill;
            bill /= 1000;
            endI++;
        }
        return rt;
    }
};

In Java
注意空格
class Solution {
    private String[] units = {""," Thousand"," Million"," Billion"};
    private String[] singleDigits = {"One","Two","Three","Four","Five","Six","Seven","Eight","Nine"};
    private String[] doubleDigitsTenth = {"Ten","Eleven","Twelve","Thirteen","Fourteen","Fifteen","Sixteen","Seventeen","Eighteen","Nineteen"};
    private String[] doubleDigits = {"Twenty","Thirty","Forty","Fifty","Sixty","Seventy","Eighty","Ninety"};
    
    public String numberToWords(int num) {
        if (num == 0) return "Zero";
        String rt = "";
        for (int i = 0; i < 4; i++) {
            String cur = toWords((num % 1000), units[i]);
            if (!rt.isEmpty() && !cur.isEmpty()) rt = " " + rt;
            rt = cur + rt;
            num /= 1000; 
        }
        
        return rt;
    }
    
    private String toWords(int num, String unit) {
        String s = "";
        if (num == 0) return s;
        
        if (num >= 100) {
            s += singleDigits[num / 100 - 1] + " Hundred";
            num %= 100;
        }
        if (num > 9 && num < 20) {
            if (!s.isEmpty()) s += " ";
            s += doubleDigitsTenth[num % 10];
        } else {
            if (num > 19) {
                if (!s.isEmpty()) s += " ";
                s += doubleDigits[num / 10 - 2];
                num %= 10;
            }
            if (num != 0) {
                if (!s.isEmpty()) s += " ";
                s += singleDigits[num - 1];
            }
        }
        
        return s + unit;
    }
}