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;
    }
}

Saturday, September 19, 2015

Day 127, #248 #249 #250 #252 #253 #254 #255 Strobogrammatic Number III, Group Shifted Strings, Count Univalue Subtrees, Meeting Rooms, Meeting Rooms II, Factor Combinations, Verify Preorder Sequence in Binary Search Tree

Strobogrammatic Number III
A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at upside down).
Write a function to count the total strobogrammatic numbers that exist in the range of low <= num <= high.
For example,
Given low = "50", high = "100", return 3. Because 69, 88, and 96 are three strobogrammatic numbers.
Note:
Because the range might be a large number, the low and high numbers are represented as string.
-----------------------------------
类似 II。 对最后生成的数字跟low和high做对比,如果在范围内,count就加1
面试时不要用global variable
class Solution {
public:
    string low;
    string high;
    bool compareStrings(string &s1,string &s2) {
        if (s1.length() != s2.length()) return s1.length() < s2.length();
        for (int i = 0; i < s1.length(); i++) {
            if (s1[i] != s2[i]) return s1[i] < s2[i]; 
        }
        
        return true;
    }
    
    void helper(vector &rt,string s,int left,int right,int &count) {
        if (left > right) {
            if (s[0] != '0' && compareStrings(low,s) && compareStrings(s,high)) {
                count++;
            }
            return;
        }
        if (left != 0) {
            s[left] = '0',s[right] = '0';
            helper(rt,s,left + 1,right - 1,count);
        }
        s[left] = '1',s[right] = '1';
        helper(rt,s,left + 1,right - 1,count);
        s[left] = '8',s[right] = '8';
        helper(rt,s,left + 1,right - 1,count);
        if (left != right) {
            s[left] = '6',s[right] = '9';
            helper(rt,s,left + 1,right - 1,count);
            s[left] = '9',s[right] = '6';
            helper(rt,s,left + 1,right - 1,count);
        }
    }

    int strobogrammaticInRange(string low, string high) {
        this->low = low;
        this->high = high;
        int count = 0;
        vector rt;
        for (int i = low.length(); i <= high.length(); i++) {
            string s(i,'\0');
            helper(rt,s,0,i - 1,count);
        }
        if (low == "0") return count + 1;
        return count;
    }
};

Group Shifted Strings
Given a string, we can "shift" each of its letter to its successive letter, for example: "abc" -> "bcd". We can keep "shifting" which forms the sequence:
"abc" -> "bcd" -> ... -> "xyz"
Given a list of strings which contains only lowercase alphabets, group all strings that belong to the same shifting sequence.
For example, given: ["abc", "bcd", "acef", "xyz", "az", "ba", "a", "z"],
Return:
[
  ["abc","bcd","xyz"],
  ["az","ba"],
  ["acef"],
  ["a","z"]
]
Note: For the return value, each inner list's elements must follow the lexicographic order.
-----------------------------------
注意:是string里的每一个字母都往后挪一次

class Solution {
public:
    vector<vector<string>> groupStrings(vector<string>& strings) {
        unordered_map<string,vector<string>> dic;
        for (int i = 0; i < strings.size(); i++) {
            string key = "";
            
            for (int j = 1; j < strings[i].length(); j++) {
                int diff = strings[i][j] - strings[i][j - 1];
                if (diff >= 0) {
                    key += to_string(diff) + ",";
                }else {
                    key += to_string(diff + 26) + ",";
                }
            }
            dic[key].push_back(strings[i]);
        }
        
        vector<vector<string>> rt;
        for (auto kv : dic) {
            vector<string> t = kv.second;
            sort(t.begin(),t.end());
            rt.push_back(t);
        }
        
        return rt;
    }
};

Count Univalue Subtrees
Given a binary tree, count the number of uni-value subtrees.
A Uni-value subtree means all nodes of the subtree have the same value.
For example:
Given binary tree,

              5
             / \
            1   5
           / \   \
          5   5   5


return 4.
--------------------------------------
uni-value subtree的定义是tree里所有的node都含有相同的值

/**
 * 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:
    string helper(TreeNode *root, int &count) {
        if (root == NULL) {
            return "";
        }
        
        string left = helper(root->left,count);
        string right = helper(root->right,count);
        string val = to_string(root->val);
        if ((left == "" || val == left) && (val == right || right == "")) {
            count++;
            return val;
        }
        return "#";
    }

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

Meeting Rooms
Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],...] (si < ei), determine if a person could attend all meetings.
For example,
Given [[0, 30],[5, 10],[15, 20]],
return false.
------------------------------------------

/**
 * Definition for an interval.
 * struct Interval {
 *     int start;
 *     int end;
 *     Interval() : start(0), end(0) {}
 *     Interval(int s, int e) : start(s), end(e) {}
 * };
 */
class Solution {
public:
    class Cmp {
    public:
        bool operator() (Interval &i1, Interval &i2) {
            if (i1.start == i2.start) {
                return i1.end < i2.end;
            }
            return i1.start < i2.start;
        }  
    };

    bool canAttendMeetings(vector<Interval>& intervals) {
        sort(intervals.begin(),intervals.end(),Cmp());
        for (int i = 1; i < intervals.size(); i++) {
            if (intervals[i].start < intervals[i - 1].end) {
                return false;
            }
        }
        return true;
    }
};

Meeting Rooms II
Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],...] (si < ei), find the minimum number of conference rooms required.
For example,
Given [[0, 30],[5, 10],[15, 20]],
return 2.
-------------------------------------
sort所有时间点,从头开始扫,如果是开始时间,count + 1。结束时间,count - 1

/**
 * Definition for an interval.
 * struct Interval {
 *     int start;
 *     int end;
 *     Interval() : start(0), end(0) {}
 *     Interval(int s, int e) : start(s), end(e) {}
 * };
 */
class Solution {
public:
    static bool cmp(int i1, int i2) {
        if (abs(i1) == abs(i2)) return i1 < i2;
        return abs(i1) < abs(i2);
    }

    int minMeetingRooms(vector<Interval>& intervals) {
        vector<int> times;
        for (int i = 0; i < intervals.size(); i++) {
            times.push_back(intervals[i].start);
            times.push_back(-intervals[i].end);
        }
        
        sort(times.begin(),times.end(),cmp);
        int minNumber = 0;
        int cur = 0;
        for (int i = 0; i < times.size(); i++) {
            if (times[i] >= 0) {
                cur++;
                minNumber = max(minNumber,cur);
            }else {
                cur--;
            }
        }
        
        return minNumber;
    }
};

Java, with PriorityQueue
/**
 * Definition for an interval.
 * public class Interval {
 *     int start;
 *     int end;
 *     Interval() { start = 0; end = 0; }
 *     Interval(int s, int e) { start = s; end = e; }
 * }
 */
class Solution {
    public int minMeetingRooms(Interval[] intervals) {
        if (intervals.length <= 1) return intervals.length;
        
        Arrays.sort(intervals, (a, b) -> a.start - b.start);
        PriorityQueue<Integer> q = new PriorityQueue<>();
        q.add(intervals[0].end);
        int size = 1;
        
        for (int i = 1; i < intervals.length; i++) {
            if (q.peek() <= intervals[i].start) {
                q.poll();
            }
            q.add(intervals[i].end);
            size = Math.max(size, q.size());
        }
        
        return size;
    }
}

Factor Combinations
Numbers can be regarded as product of its factors. For example,
8 = 2 x 2 x 2;
  = 2 x 4.
Write a function that takes an integer n and return all possible combinations of its factors.
Note: 
  1. Each combination's factors must be sorted ascending, for example: The factors of 2 and 6 is [2, 6], not [6, 2].
  2. You may assume that n is always positive.
  3. Factors should be greater than 1 and less than n.
Examples: 
input: 1
output: 
[]
input: 37
output: 
[]
input: 12
output:
[
  [2, 6],
  [2, 2, 3],
  [3, 4]
]
input: 32
output:
[
  [2, 16],
  [2, 2, 8],
  [2, 2, 2, 4],
  [2, 2, 2, 2, 2],
  [2, 4, 4],
  [4, 8]
]
--------------------------------------------------------
典型的combination,注意边界条件
class Solution {
public:
    void combination(vector> &rt, int n,vector v,int start,int orig) {
        if (n == 0 || start == orig) return;
        if (n == 1) {
            vector t = v;
            rt.push_back(t);
            return;
        }
        
        for (int i = start; i <= n; i++) {
            if (n % i != 0) continue;
            v.push_back(i);
            combination(rt,n / i,v,i,orig);
            v.pop_back();
        }
    }

    vector> getFactors(int n) {
        vector> rt;
        if (n == 1) return rt;
        vector v;
        combination(rt,n,v,2,n);
        return rt;
    }
};

Verify Preorder Sequence in Binary Search Tree
Given an array of numbers, verify whether it is the correct preorder traversal sequence of a binary search tree.
You may assume each number in the sequence is unique.
Follow up:
Could you do it using only constant space complexity?
------------------------------------------------------
用stack,有额外空间
#1 因为是preorder,一开始队列成递减(如果root没有左子树,则为只有一个元素的递减数列),压入所有遇到的node
#2 遇到拐点时说明此node为之前某一个node的右子树,则开始pop stack,直到找到之前的那个node,然后将minVal设好,pop掉的部分都为已经验证过的,符合bst条件的
#3 如果在遍历的过程中发现一个node的值小于minVal,则返回false

class Solution {
public:
    bool verifyPreorder(vector<int>& preorder) {
        if (preorder.size() == 0) return true;
        stack<int> st;
        int minVal = INT_MIN;
        st.push(preorder[0]);
        
        for (int i = 1; i < preorder.size(); i++) {
            if (preorder[i] < minVal) return false;
            if (preorder[i] > preorder[i - 1]) {
                while (!st.empty() && preorder[i] > st.top()) {
                    minVal = st.top();
                    st.pop();
                }
            }
            
            st.push(preorder[i]);
        }
        
        return true;
    }
};
COME_BACK
O(1) 空间,run time complexity未知,最坏可能为O(n^2)
bool verifyPreorder(vector<int>& preorder) {
        if (preorder.size() == 0) return true;
        int minIndex = -1;
        int top = 0, end = 0;
        
        for (int i = 1; i < preorder.size(); i++) {
            if (minIndex != -1 && preorder[i] < preorder[minIndex]) return false;
            if (preorder[i] > preorder[i - 1]) {
                while (top >= end && preorder[i] > preorder[top]) {
                    minIndex = top;
                    top--;
                }
            }
            if (top < end) end = i;
            top = i;
        }
        
        return true;
    }

Sunday, September 13, 2015

Day 126, #243 #244 #245 Shortest Word Distance, Shortest Word Distance II, Shortest Word Distance III

Shortest Word Distance
Given a list of words and two words word1 and word2, return the shortest distance between these two words in the list.
For example,
Assume that words = ["practice", "makes", "perfect", "coding", "makes"].
Given word1 = “coding”word2 = “practice”, return 3.
Given word1 = "makes"word2 = "coding", return 1.
Note:
You may assume that word1 does not equal to word2, and word1 and word2 are both in the list.
----------------------------------------------------------------------------
class Solution {
public:
    int shortestDistance(vector<string>& words, string word1, string word2) {
        int shortest = words.size();
        int pos1 = -words.size(), pos2 = -words.size();
        for (int i = 0; i < words.size(); i++) {
            if (words[i] == word1) {
                pos1 = i;
                shortest = min(shortest,pos1 - pos2);
            }
            if (words[i] == word2) {
                pos2 = i;
                shortest = min(shortest,pos2 - pos1);
            }
        }
        return shortest;
    }
};

Shortest Word Distance II
This is a follow up of Shortest Word Distance. The only difference is now you are given the list of words and your method will be called repeatedly many times with different parameters. How would you optimize it?
Design a class which receives a list of words in the constructor, and implements a method that takes two words word1 and word2 and return the shortest distance between these two words in the list.
For example,
Assume that words = ["practice", "makes", "perfect", "coding", "makes"].
Given word1 = “coding”word2 = “practice”, return 3.
Given word1 = "makes"word2 = "coding", return 1.
Note:
You may assume that word1 does not equal to word2, and word1 and word2 are both in the list.
-----------------------------------------------------------------------

class WordDistance {
public:
    WordDistance(vector<string>& words) {
        for (int i = 0; i < words.size(); i++) {
            if (dic.find(words[i]) == dic.end()) {
                vector<int> t = {i};
                dic[words[i]] = t;
            }else {
                dic[words[i]].push_back(i);
            }
        }
    }

    int shortest(string word1, string word2) {
        int i = 0, j = 0;
        int distance = INT_MAX;
        
        while (i < dic[word1].size() && j < dic[word2].size()) {
            distance = min(distance,abs(dic[word1][i] - dic[word2][j]));
            if (dic[word1][i] < dic[word2][j]) {
                i++;
            }else {
                j++;
            }
        }
        
        return distance;
    }
private:
    unordered_map<string,vector<int>> dic;
};


// Your WordDistance object will be instantiated and called as such:
// WordDistance wordDistance(words);
// wordDistance.shortest("word1", "word2");
// wordDistance.shortest("anotherWord1", "anotherWord2");

Shortest Word Distance III
This is a follow up of Shortest Word Distance. The only difference is now word1 could be the same as word2.
Given a list of words and two words word1 and word2, return the shortest distance between these two words in the list.
word1 and word2 may be the same and they represent two individual words in the list.
For example,
Assume that words = ["practice", "makes", "perfect", "coding", "makes"].
Given word1 = “makes”word2 = “coding”, return 1.
Given word1 = "makes"word2 = "makes", return 3.
Note:
You may assume word1 and word2 are both in the list.
---------------------------------------------------------------------
class Solution {
public:
    int sameWords(vector<string>& words, string word) {
        int distance = words.size();
        int pre = -words.size();
        for (int i = 0; i < words.size(); i++) {
            if (words[i] == word) {
                distance = min(distance,i - pre);
                pre = i;
            }
        }
        return distance;
    }

    int shortestWordDistance(vector<string>& words, string word1, string word2) {
        if (word1 == word2) return sameWords(words,word1);
        int pos1 = -words.size(), pos2 = -words.size();
        int shortest = words.size();
        for (int i = 0; i < words.size(); i++) {
            if (words[i] == word1) {
                shortest = min(shortest,i - pos2);
                pos1 = i;
            }else if (words[i] == word2) {
                shortest = min(shortest,i - pos1);
                pos2 = i;
            }
        }
        
        return shortest;
    }
};

Thursday, September 10, 2015

zenefits interview questions

 ref: http://www.mitbbs.com/article_t1/JobHunting/32952623_0_1.html
online test

---------------------------------------------------------
ref: http://www.mitbbs.com/article_t/JobHunting/32931597.html
String s1 = "
waeginsapnaabangpisebbasepgnccccapisdnfngaabndlrjngeuiogbbegbuoecccc";
String s2 = "a+b+c-";

s2的形式是一个字母加上一个符号,正号代表有两个前面的字符,负号代表有四个,也
就是说s2其实是"aabbcccc",不考虑invalid。
在s1中,找出连续或者不连续的s2,也就是说从s1中找出"aa....bb.....cccc",abc顺
序不能变,但是之间可以有零个或多个字符,返回共有多少个。在上面这个例子中,有
四个。
--------------------------------------------------------
ref: http://www.mitbbs.com/article_t/JobHunting/33043355.html

A, B两个String
//example
A = XYZ;
A^2 = XXYYZZ;
A^3 = XXXYYYZZZ;

B = XXadhflakjhelXXzzqqkkpoYYadadfhgakheZafhajkefhlZadhflkejhZfagjhfebhh

A^2 是B的subsequence, 所以
return k = 2;

A可能有重复的char, B可能有其他字符, 求k.

Day 125, #279 #280 Perfect Squares, Wiggle Sort, H-Index II

Perfect Squares
Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...) which sum to n.
For example, given n = 12, return 3 because 12 = 4 + 4 + 4; given n = 13, return 2 because 13 = 4 + 9.
----------------------------------------------------
O(n * sqrt(n)) dp递归, 同样复杂度,但过不了oj
class Solution {
public:
    int helper(unordered_map<int,int> &dic,int n) {
        if (n < 4) return n;
        if (dic.find(n) != dic.end()) return dic[n];
        
        int minLen = INT_MAX;
        int i = (int)sqrt(n);
     for (; i > 0; i--) {
      minLen = min(minLen,helper(dic,n - i * i) + 1);
     }
     dic[n] = minLen;
     return minLen;
    }

    int numSquares(int n) {
        unordered_map<int,int> dic;
     return helper(dic,n);
    }
};

COME_BACK: 注意如何从递归转化为遍历
遍历dp
class Solution {
public:
    int numSquares(int n) {
        vector<int> dp(n + 1,INT_MAX);
        dp[0] = 0;
        
        for (int i = 0; i <= n; i++) {
            for (int j = 1; j *j + i <= n; j++) {
                dp[i + j * j] = min(dp[i + j * j],dp[i] + 1);
            }
        }
        return dp[n];
    }
};

In Java
class Solution {
    public int numSquares(int n) {
        int[] dp = new int[n + 1];
        Arrays.fill(dp, Integer.MAX_VALUE);
        dp[0] = 0;
        
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j * j <= i; j++) {
                dp[i] = Math.min(dp[i], dp[i - j * j] + 1);
            }
        }
        
        return dp[n];
    }
}

Wiggle Sort
Given an unsorted array nums, reorder it in-place such that nums[0] <= nums[1] >= nums[2] <= nums[3]....
For example, given nums = [3, 5, 2, 1, 6, 4], one possible answer is [1, 6, 2, 5, 3, 4].
-------------------------------------------
class Solution {
public:
    void wiggleSort(vector<int>& nums) {
        for (int i = 0; i < (int)nums.size() - 1; i++) {
            if (i % 2 == 0 && nums[i] > nums[i + 1]) {
                swap(nums[i],nums[i + 1]);
            }else if (i % 2 == 1 && nums[i] < nums[i + 1]) {
                swap(nums[i],nums[i + 1]);
            }
        }
    }
};

H-Index II
Follow up for H-Index: What if the citations array is sorted in ascending order? Could you optimize your algorithm?
Hint:
  1. Expected runtime complexity is in O(log n) and the input is sorted.
--------------------------------------------------------------------------------
binary search
class Solution {
public:
    int hIndex(vector<int>& citations) {
        int left = 0, right = citations.size() - 1;
        int high = 0;
        int n = citations.size();
        while (left <= right) {
            int mid = (left + right) / 2;
            if (citations[mid] == n - mid) {
                return n - mid;
            }
            if (citations[mid] > n - mid) {
                high = max(high,n - mid);
                right = mid - 1;
            }else {
                left = mid + 1;
            }
        }
        
        return high;
    }
};