Monday, May 27, 2013

Day 31, 23, Merge k Sorted Lists

Merge k Sorted Lists
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
--------------------------------------------------------------
Solution #1 O(k*n)
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *merge2Lists (ListNode *l1, ListNode *l2) {
        ListNode *ret,*cur;
        if (l1 == NULL) {
            return l2;
        }
        if (l2 == NULL) {
            return l1;
        }
        if (l1->val < l2->val) {
            ret = l1;
            cur = l1;
            l1 = l1->next;
        }else {
            ret = l2;
            cur = l2;
            l2 = l2->next;
        }
        while (l1 != NULL && l2 != NULL) {
            if (l1->val < l2->val) {
                cur->next = l1;
                cur = cur->next;
                l1 = l1->next;
            }else {
                cur->next = l2;
                cur = cur->next;
                l2 = l2->next;
            }
        }
        if (l1 == NULL) {
            cur->next = l2;
        }else {
            cur->next = l1;
        }
        return ret;
    }
    

    ListNode *mergeKLists(vector<ListNode *> &lists) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if (lists.size() == 0) return NULL;
        ListNode *ret = lists[0];
        for (int i=1;i<lists.size();i++) {
            ret = merge2Lists(ret,lists[i]);
        }
        return ret;
    }
};

Solution #2, O(nlogk), using Priority Queue
note struct of comparison function and declaration of priority queue
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    struct comp{
        bool operator()(const ListNode* n1, const ListNode* n2){
            return n1->val > n2->val;
        }
    };

    ListNode *mergeKLists(vector<ListNode *> &lists) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        priority_queue<ListNode*,vector<ListNode*>,comp> heap;
        ListNode *ret=NULL,*cur;
        for (int i=0;i<lists.size();i++) {
            if (lists[i] != NULL) {
                heap.push(lists[i]);
            }
        }
        
        while (!heap.empty()) {
            ListNode *min = heap.top();
            heap.pop();
            if (ret == NULL) {
                ret = min;
                cur = min;
            }else {
                cur->next = min;
                cur = cur->next;
            }
            if (min->next != NULL) {
                heap.push(min->next);
            }
        }
        return ret;
    }
};
Update on Sep-11-2014
Solution #3, push all nodes in priority_queue, then output will be in order
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    struct cmp {
        bool operator()(const ListNode* l1, const ListNode* l2) {
            return l1->val > l2->val;
        }
    };

    ListNode *mergeKLists(vector<ListNode *> &lists) {
        ListNode *dummy = new ListNode(INT_MIN);
        priority_queue<ListNode*,vector<ListNode*>,cmp> heap;
        bool flag = true;
        
        while (flag) {
            flag = false;
            for (int i = 0; i < lists.size(); i++) {
                if (lists[i] != NULL) {
                    flag = true;
                    heap.push(lists[i]);
                    lists[i] = lists[i]->next;
                }
            }
        }
        
        ListNode *head = dummy;
        while (!heap.empty()) {
            ListNode *t = heap.top();
            head->next = t;
            heap.pop();
            head = t;
        }
        head->next = NULL; // prevent infinite loop
        
        return dummy->next;
    }
};
Solution #4, merge all pairs of two adjacent lists for each iteration. O(nlog(k)), n is the total elements from all lists
Update on Nov-26-2014
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *merge2Lists (ListNode *l1, ListNode *l2) {
        ListNode *ret,*cur;
        if (l1 == NULL) {
            return l2;
        }
        if (l2 == NULL) {
            return l1;
        }
        if (l1->val < l2->val) {
            ret = l1;
            cur = l1;
            l1 = l1->next;
        }else {
            ret = l2;
            cur = l2;
            l2 = l2->next;
        }
        while (l1 != NULL && l2 != NULL) {
            if (l1->val < l2->val) {
                cur->next = l1;
                cur = cur->next;
                l1 = l1->next;
            }else {
                cur->next = l2;
                cur = cur->next;
                l2 = l2->next;
            }
        }
        if (l1 == NULL) {
            cur->next = l2;
        }else {
            cur->next = l1;
        }
        return ret;
    }

    ListNode *mergeKLists(vector<ListNode *> &lists) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if (lists.size() == 0) return NULL;
        
        int size = lists.size();    
        while (size != 1) {
            
            for (int i = 0; i < size; i = i + 2) {
                if (i + 1 < size) {
                    lists[i / 2] = merge2Lists(lists[i],lists[i + 1]);
                }else{
                    lists[i / 2] = lists[i];
                }
            }
            size = size / 2 + size % 2;
        }
        
        return lists[0];
    }
};

与上面同样思路,但是用递归
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode *dummy = new ListNode(0), *itr = dummy;
        while (l1 != NULL && l2 != NULL) {
            if (l1->val > l2->val) {
                itr->next = l2;
                l2 = l2->next;
                itr = itr->next;
            }else {
                itr->next = l1;
                l1 = l1->next;
                itr = itr->next;
            }
        }
        
        if (l1 == NULL) {
            itr->next = l2;
        }
        if (l2 == NULL) {
            itr->next = l1;
        }
        return dummy->next;
    }

    ListNode* helper(vector<ListNode*> &lists,int start,int end) {
        if (start > end) return NULL;
        if (start == end) return lists[start];
        int mid = (start + end) / 2;
        ListNode *l1 = helper(lists,start,mid);
        ListNode *l2 = helper(lists,mid + 1,end);
        return mergeTwoLists(l1,l2);
    }

    ListNode* mergeKLists(vector<ListNode*>& lists) {
        return helper(lists,0,lists.size() - 1);
    }
};
Java, 用priority queue
时间O(N * log k), 空间为O(k), N为总node的个数,k为list的数量。
先把所有的头指针插入到queue,然后一个个pop。把刚pop出来的node的一下个,推回queue
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        PriorityQueue que = new PriorityQueue<>((a, b) -> {
            return a.val - b.val;
        });
                
        for (ListNode node : lists) {
            if (node != null) que.add(node);
        }
        
        ListNode dummy = new ListNode(0);
        ListNode itr = dummy;

        while (!que.isEmpty()) {
            ListNode next = que.poll();
            if (next.next != null) que.add(next.next);
            itr.next = next;
            itr = next;
        }
        
        return dummy.next;
    }
}
如果可以重复利用原来的array的话,空间可以算是O(1)
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if (lists == null || lists.length == 0) return null;
        List rt = Arrays.asList(lists);
        while (rt.size() != 1) {
            rt = divide(rt);
        }
        
        return rt.get(0);
    }
    
    private List divide(List lists) {
        int n = lists.size();
        List rt = new ArrayList<>();
        for (int i = 0; i < n / 2; i++) {
            rt.add(mergeTwo(lists.get(i), lists.get(n - 1 - i)));
        }
        
        if (n % 2 == 1) rt.add(lists.get(n / 2));
        
        return rt;
    }
    
    private ListNode mergeTwo(ListNode node1, ListNode node2) {
        
        if (node1 == null) return node2;
        if (node2 == null) return node1;
            
        ListNode dummy = new ListNode(0);
        ListNode itr;
        if (node1.val > node2.val) {
            dummy.next = node2;
            node2 = node2.next;
        }else {
            dummy.next = node1;
            node1 = node1.next;
        }
        itr = dummy.next;
        
        while (node1 != null && node2 != null) {
            
            if (node1.val > node2.val) {
                itr.next = node2;
                itr = node2;
                node2 = node2.next;
            }else {
                itr.next = node1;
                itr = node1;
                node1 = node1.next;
            }
        }
        
        if (node1 != null) {
            itr.next = node1;
        }
        if (node2 != null) {
            itr.next = node2;
        }
        
        return dummy.next;
    }
}

Sunday, May 26, 2013

Day 30, 18,22, 4Sum, Generate Parentheses

4Sum
Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
Note:
  • Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ? b ? c ? d)
  • The solution set must not contain duplicate quadruplets.
    For example, given array S = {1 0 -1 0 -2 2}, and target = 0.

    A solution set is:
    (-1,  0, 0, 1)
    (-2, -1, 1, 2)
    (-2,  0, 0, 2)
 -----------------------------------------------------------------------------------------
O(n^3), solution based on 3sum
the efficiency of the best solution for m sum is O(n^(m-1)) 

class Solution {
public:
    vector<vector<int> > fourSum(vector<int> &num, int target) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        vector<vector<int> > result;
        if (num.size() < 4) {
            return result;
        }
        sort(num.begin(),num.end());
        for (int j=0;j<num.size()-3;j++) {
            int a = num[j];
            // 3sum
            for (int i=j+1;i<num.size()-2;i++) {
                int b = num[i];
                int left = i+1;
                int right = num.size() - 1;
                // 2sum
                while (left < right) {
                    int c = num[left];
                    int d = num[right];
                    int sum = a + b + c + d;
                    if (sum == target) {
                        vector<int> t = {a,b,c,d};
                        if (find(result.begin(), result.end(), t) == result.end()) {
                            result.push_back(t);
                        }
                        right--;
                        left++;
                    }else if (sum < target) {
                        left++;
                    }else {
                        right--;
                    }
                }
            }
        
        }
    }
};
Update on Sep-10-2014
Solution #2, similar to the update of 3sum
class Solution {
public:
    vector<vector<int> > fourSum(vector<int> &num, int target) {
        vector<vector<int> > rt;
        if (num.size() < 4) {
            return rt;
        }
        sort(num.begin(), num.end());
        
        
        for (int first = 0; first < num.size() - 3; first++) {
            if (first > 0 && num[first] == num[first - 1]) {
                continue;
            }
            
            for (int second = first + 1; second < num.size() - 2; second++) {
                if (second > first + 1 && num[second] == num[second - 1]) {
                    continue;
                }   
                int left = second + 1;
                int right = num.size() - 1;
                while (left < right) {
                    int sum = num[first] + num[second] + num[left] + num[right];
                    if (sum == target) {
                        vector<int> v(4);
                        v[0] = num[first];
                        v[1] = num[second];
                        v[2] = num[left];
                        v[3] = num[right];
                        rt.push_back(v);
                        
                        while (num[left] == num[left + 1]) {
                            left++;
                        }
                        while (num[right] == num[right - 1]) {
                            right--;
                        }
                    }
                    
                    if (sum < target) {
                        left++;
                    }else {
                        right--;
                    }
                }
            }
        }
        
        return rt;
    }
};
Generate Parentheses
Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
For example, given n = 3, a solution set is:
"((()))", "(()())", "(())()", "()(())", "()()()"
 -----------------------------------------------------------------
Solution #1 
class Solution {
public:
    vector<string> rec (int n, int total) {
        vector<string> ret;
        if (n == 1) {
            ret.push_back("(");
            return ret;
        }
        ret = rec(n-1,total);
        vector<string> retNew;
        for (int i=0;i<ret.size();i++) {
            // calculate the balance of the current string
            int bal = 0;
            for (int j=0;j<ret[i].length();j++) {
                if (ret[i][j] == '(') {
                    bal++;
                }else {
                    bal--;
                }
            }
            
            if (bal > 0) {
                string s = ret[i] + ')';
                retNew.push_back(s);
            }
            if (bal < (total-n)) {
                string s = ret[i] + '(';
                retNew.push_back(s);
            }           
        }
        return retNew;
    }

    vector<string> generateParenthesis(int n) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        return rec(2*n,2*n);
    }
};
Solution #2, similar algorithm, from internet
vector<string> generateParenthesis(int n) {
    vector<string> ans;
    if (n>0) generator(ans, "", 0, 0, n);
    return ans;
}

void generator(vector<string> & ans, string s, int l, int r, int n) { 
    if (l == n) {
        ans.push_back(s.append(n-r, ')'));
        return;
    }
    generator(ans, s+'(', l+1, r, n);
    if (l>r) generator(ans, s+")", l, r+1, n);
}
Update on Sep-10-2014
Solution #3, re-factoried, increased readability
class Solution {
public:
    void rec(vector<string> &rt, string str, int left, int right, int n) {
        if (left == n && right == n) {
            rt.push_back(str);
        }
        
        if (left < n) {
            rec(rt,str + "(",left + 1, right, n);
        }
        if (right < left) {
            rec(rt,str + ")",left, right + 1, n);
        }
        
    }

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

Saturday, May 25, 2013

Day 29, 17, Letter Combinations of a Phone Number

Letter Combinations of a Phone Number
Given a digit string, return all possible letter combinations that the number could represent.
A mapping of digit to letters (just like on the telephone buttons) is given below.

Input:Digit string "23"
Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
Note:
Although the above answer is in lexicographical order, your answer could be in any order you want.
-------------------------------------------------------------------
There's a better solution - recursive permutation

class Solution {
public:

    vector<string> recur (string digits, unordered_map<char,string> &k) {
        if (digits.length() == 1) {
            vector<string> start;
            for (int i=0;i<k[digits[0]].length();i++) {
                string temp;
                temp += k[digits[0]][i];
                start.push_back(temp);
            }
            return start;
        }
        vector<string> t = recur(digits.substr(0,digits.length()-1),k);
        vector<string> ret;
        for (int i=0;i<t.size();i++) {
            for (int j=0;j<k[digits.back()].length();j++) {
                string str = t[i] + k[digits.back()][j];
                ret.push_back(str);
            }
        }
        return ret;
    }


    vector<string> letterCombinations(string digits) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        vector<string> ret;
        if (digits == "") {
            ret.push_back("");
            return ret;
        }
        unordered_map<char,string> k;
        k['2'] = "abc"; 
        k['3'] = "def";
        k['4'] = "ghi";
        k['5'] = "jkl";
        k['6'] = "mno";
        k['7'] = "pqrs";
        k['8'] = "tuv";
        k['9'] = "wxyz"; 
        return recur(digits,k);

    }
};
Update on Sep-10-2014
refactoried, use index
class Solution {
public:
    void rec (vector<string> &rt, string str, string digits, int index, unordered_map<char,string> &k) {
        if (index == digits.length()) {
            rt.push_back(str);
            return;
        }
        char digit = digits[index];
        string letters = k[digit];
        for (int i = 0; i < letters.length(); i++) {
            rec(rt,str + letters[i],digits,index + 1,k);
        }
        
    }


    vector<string> letterCombinations(string digits) {
        vector<string> rt;
        if (digits.length() == 0) {
            rt.push_back("");
            return rt;
        }
        
        unordered_map<char,string> k;
        k['2'] = "abc";
        k['3'] = "def";
        k['4'] = "ghi";
        k['5'] = "jkl";
        k['6'] = "mno";
        k['7'] = "pqrs";
        k['8'] = "tuv";
        k['9'] = "wxyz"; 
        
        rec(rt,"",digits,0,k);
        return rt;
    }
};
Update on Jan-19-2015
BFS
class Solution {
public:
    unordered_map<char,string> letters;
    vector<string> rt;
    
    void bfs(string digits) {
        for (int i = 0; i < digits.length(); i++) {
            string st = letters[digits[i]];
            vector<string> cpRt;
            
            for (int j = 0; j < st.length(); j++) {
                vector<string> cp = rt;
                for (int k = 0; k < cp.size(); k++) {
                    cp[k] = cp[k] + st[j];
                }
                cpRt.insert(cpRt.end(),cp.begin(),cp.end());
            }
            rt = cpRt;
        }
    }

    vector<string> letterCombinations(string digits) {
        letters['1'] = "";
        letters['2'] = "abc";
        letters['3'] = "def";
        letters['4'] = "ghi";
        letters['5'] = "jkl";
        letters['6'] = "mno";
        letters['7'] = "pqrs";
        letters['8'] = "tuv";
        letters['9'] = "wxyz";
        letters['0'] = " ";
        
        rt.push_back("");
        bfs(digits);
        return rt;
    }
};

Java
public class Solution {
    public List<String> letterCombinations(String digits) {
        if (digits == null || digits.length() == 0) return new ArrayList<>();
        
        Map<Character, String> map = getDigitsMap();
        List<String> rt = new ArrayList<>();
        rt.add("");
        
        for (int i = 0; i < digits.length(); i++) {
            rt = appendNewChar(map.get(digits.charAt(i)), rt);    
        }
        
        return rt;
    }
    
    private List<String> appendNewChar(String source, List<String> rt) {
        List<String> newRt = new ArrayList<String>();
        for (String s : rt) {
            for (int i = 0; i < source.length(); i++) {
                newRt.add(s + Character.toString(source.charAt(i)));
            }
        }
        
        return newRt;        
    }

    private Map<Character, String> getDigitsMap() {
        Map<Character, String> map = new HashMap<>();
        map.put('0',"");
        map.put('1', "");
        map.put('2', "abc");
        map.put('3', "def");
        map.put('4',"ghi");
        map.put('5',"jkl");
        map.put('6',"mno");
        map.put('7',"pqrs");
        map.put('8',"tuv");
        map.put('9',"wxyz");
        
        return map;
    }
}

Recursion
public class Solution {
    public List<String> letterCombinations(String digits) {
        if (digits == null || digits.length() == 0) return new ArrayList<>();
        
        Map<Character, String> map = getDigitsMap();
        List<String> rt = new ArrayList<>();
        rec(map, rt, "", digits, 0);
        
        return rt;
    }
    
    private void rec(Map<Character, String> map, List<String> rt, String comb, String digits, int index) {
        if (index == digits.length()) {
            rt.add(comb);
            return;
        }
        
        String source = map.get(digits.charAt(index));
        for (int i = 0; i < source.length(); i++) {
            rec(map, rt, comb + Character.toString(source.charAt(i)),  digits, index + 1);
        }
    }

    private Map<Character, String> getDigitsMap() {
        Map<Character, String> map = new HashMap<>();
        map.put('0',"");
        map.put('1', "");
        map.put('2', "abc");
        map.put('3', "def");
        map.put('4',"ghi");
        map.put('5',"jkl");
        map.put('6',"mno");
        map.put('7',"pqrs");
        map.put('8',"tuv");
        map.put('9',"wxyz");
        
        return map;
    }
}

Wednesday, May 22, 2013

Day 28, 12, 15,16, Integer to Roman, 3Sum, 3Sum Closest

Integer to Roman
Given an integer, convert it to a roman numeral.
Input is guaranteed to be within the range from 1 to 3999.
--------------------------------------------------
set up an dictionary and an array of values in order
pay attention to "4", "9", "19", "989", etc
先检查 == 4,再检查 == 9
COME_BACK
class Solution {
public:
    string intToRoman(int num) {
        unordered_map k;
        k[1] = 'I';
        k[5] = 'V';
        k[10] = 'X';
        k[50] = 'L';
        k[100] = 'C';
        k[500] = 'D';
        k[1000] = 'M';
        string s = "";
        vector order = {1000,500,100,50,10,5,1};
        
        for (int i = 0; i < 7; i++) {
            if (num / order[i] < 0) continue;
            if (num / order[i] == 4) {
                s = s + k[order[i]] + k[order[i - 1]];
                num %= order[i];
            }else if (i + 1 < 7 && num / order[i + 1] == 9) {
                s = s + k[order[i + 1]] + k[order[i - 1]];
                num %= order[i + 1]; 
            }else if (num / order[i] < 4){
                for (int j = 0; j < num / order[i]; j++) {
                    s = s + k[order[i]];
                }
                num %= order[i];
            }
        }
        
        return s;
    }
};

另一种简单方法
class Solution {
public:
    string intToRoman(int num) {
        vector<string> roman = {"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
        vector<int> numbers = {1000,900,500,400,100,90,50,40,10,9,5,4,1};
        string rt = "";
        for (int i = 0; i < 13; i++) {
            while (num >= numbers[i]) {
                rt += roman[i];
                num -= numbers[i];
            }
        }
        return rt;
    }
};

3 Sum
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
  • Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ? b ? c)
  • The solution set must not contain duplicate triplets.
    For example, given array S = {-1 0 1 2 -1 -4},

    A solution set is:
    (-1, 0, 1)
    (-1, -1, 2)
----------------------------------------------------------
Solution #1, O(n^2) time, O(n) space.  
Hash first, then find out all possible pairs, then check for existence of the remaining value
Time Limit Exceeded in large test cases, possibly 'cause of sort() and find() functions.
class Solution {
public:
    vector<vector<int> > threeSum(vector<int> &num) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        vector<vector<int> > result;
        if (num.size() < 3) {
          return result;
        }
        
        unordered_map<int,int> mapping;
        for (int i=0;i<num.size();i++) {
            if (mapping[num[i]] == NULL) {
                mapping[num[i]] = 1;
            }else {
                mapping[num[i]] = mapping[num[i]] + 1;
            }
        }
        
        for (int i=0;i<num.size()-2;i++) {
            for (int j=i+1;j<num.size()-1;j++) {
                int target = -(num[i] + num[j]);
                // check if target exists
                if (mapping[target] != NULL) {
                    // check duplication
                    if ((num[i] == target && mapping[num[i]] == 1)
                      || (num[j] == target && mapping[num[j]] == 1)) {
                          continue;
                    }
                    // check tri-plication  
                    if (num[i] == num[j] && num[i] == target && mapping[num[i]] < 3) {  
                        continue;
                    }
                    vector<int> t = {num[i],num[j],target};
                    sort(t.begin(),t.end());
                    if (find(result.begin(), result.end(), t) == result.end()) {
                        result.push_back(t);
                    }
                }
            }
        }
        return result;
    }
};
Solution #2, O(n^2) time based on 2sum's algorithm
sort first
class Solution {
public:
    vector<vector<int> > threeSum(vector<int> &num) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        vector<vector<int> > result;
        if (num.size() < 3) {
            return result;
        }
        
        sort(num.begin(),num.end());
        for (int i=0;i<num.size()-2;i++) {
            int a = num[i];
            int left = i+1;
            int right = num.size() - 1;
            // 2 sum
            while (left < right) {
                int b = num[left];
                int c = num[right];
                int sum = a + b + c;
                if (sum == 0) {
                    vector<int> t = {a,b,c};
                    if (find(result.begin(), result.end(), t) == result.end()) {
                        result.push_back(t);
                    }
                    right--;
                    left++;
                }else if (sum < 0) {
                    left++;
                }else {
                    right--;
                }
            }
        }
        return result;
    }
};
Update on Sep-10-2014
Solution #3, O(n^2), no need to check for duplicates of vectors
class Solution {
public:
    vector<vector<int> > threeSum(vector<int> &num) {
        vector<vector<int> > rt;
        if (num.size() < 3) return rt;
        sort(num.begin(),num.end());
        
        for (int i = 0; i < num.size() - 2; i++) {
            int end = num.size() - 1;
            int start = i + 1;
            if (i > 0 && num[i] == num[i -1]) {
                continue;
            }
            
            while (start < end) {
                int sum = num[i] + num[start] + num[end];
                if (sum == 0) {
                    vector<int> v;
                    v.push_back(num[i]);
                    v.push_back(num[start]);
                    v.push_back(num[end]);
                    rt.push_back(v);
                    while (num[start] == num[start + 1]) {
                        start++;
                    }
                    while (num[end] == num[end - 1]) {
                        end--;
                    }
                }
                
                if (sum < 0) {
                    start++;
                }else {
                    end--;
                }
            }
        }
        
        return rt;
    }
};

Java
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        
        Arrays.sort(nums);
        List<List<Integer>> rt = new ArrayList<>();
        
        for (int i = 0; i < nums.length - 2; i++) {
            if (i > 0 && nums[i] == nums[i - 1]) continue;
            
            int left = i + 1;
            int right = nums.length - 1;
            while (left < right) {
                if (left > i + 1 && nums[left] == nums[left - 1]) {
                    left++;
                    continue;
                }
                if (right < nums.length - 1 && nums[right] == nums[right + 1]) {
                    right--;
                    continue;
                }
                
                int sum = nums[left] + nums[right] + nums[i];
                if (sum == 0) {
                    List<Integer> r = new ArrayList<>();
                    rt.add(r);
                    r.add(nums[i]);
                    r.add(nums[left]);
                    r.add(nums[right]);
                    left++;
                    right--;
                }else if (sum < 0) {
                    left++;
                }else {
                    right--;
                }
            }
        }
        
        return rt;
    }
}
3Sum Closest
Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.
    For example, given array S = {-1 2 1 -4}, and target = 1.

    The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

----------------------------------------------------
class Solution {
public:
    int threeSumClosest(vector<int> &num, int target) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        int min = INT_MAX;
        int retSum = 0;
        sort(num.begin(),num.end());
        for (int i=0;i<num.size()-2;i++) {
            int a = num[i];
            int left = i+1;
            int right = num.size() - 1;
            // 2 sum
            while (left < right) {
                int b = num[left];
                int c = num[right];
                int sum = a + b + c;
                int dif = abs(sum - target);
                if (dif < min) {
                    min = dif; 
                    retSum = sum;
                }
                if (sum > target) {
                    right--;
                }else {
                    left++;
                }
            }
        }
        return retSum;
    }
};

Sunday, May 19, 2013

Day 27, 11, Container With Most Water

Container With Most Water
Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.
Note: You may not slant the container.
---------------------------------------
O(n), we only skip pairs that are certain to have a smaller size than the current 
class Solution {
public:
    int maxArea(vector<int> &height) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        int len = height.size();
        int maxW=0,left=0,right=len-1;
        while (left<right) {
            int curMax = (right - left) * min(height[left],height[right]);
            maxW = max(maxW,curMax);
            if (height[left] > height[right]) {
                right--;
            }else {
                left++;
            }
        }
        return maxW;
    }
};

Saturday, May 18, 2013

Day 26, 6, ZigZag Conversion

ZigZag Conversion
The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)
P   A   H   N
A P L S I I G
Y   I   R
And then read line by line: "PAHNAPLSIIGYIR" Write the code that will take a string and make this conversion given a number of rows:
string convert(string text, int nRows);
convert("PAYPALISHIRING", 3) should return "PAHNAPLSIIGYIR".
--------------------------------
Solution #1 use a vector<string>
class Solution {
public:
    string convert(string s, int nRows) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function    
        if (nRows == 1) {
            return s;
        }
        vector<string> ret(nRows); 
        for (int i=0;i<s.length();i++) {
            int row = i%(2*nRows - 2);
            if (row >= nRows) {
                row = 2*nRows - row-2;
            }
            ret[row] += s[i];
        }
        string str = "";
        for (int i=0;i<nRows;i++) {
            str += ret[i];
        }
        return str;
    }
};
Solution #2
class Solution {
public:
    string convert(string s, int numRows) {
        if (numRows == 1) return s;
        string rt = "";
        int zigSize = numRows * 2 - 2;
        for (int row = 0; row < numRows; row++) {
            for (int i = row; i < s.length(); i += zigSize) {
                rt += s[i];
                if (row != 0 && row != numRows - 1) {
                    int mid = i + (numRows - (i % zigSize) - 1) * 2;
                    if (mid < s.length()) {
                        rt += s[mid];
                    }
                }
            }
        }
        
        return rt;
    }
};

Tuesday, May 14, 2013

Questions/Thoughts for interviews

shortest path in a 2d matrix
int shortestPath(vector<vector<bool> > matrix, int target_row, int target_col) {
    vector<vector<bool> > visit(matrix.size(),vector<bool>(matrix[0).size(),true);
    queue<pair(int,int)> que;
    queue<int> count;
    que.push(make_pair(0,0));
    count.push(0);
    
    while (!que.empty()) {
        int row = que.front().first;
        int col = que.front().second;
        que.pop();
        int curCount = count.front();
        count.pop();
        
        if (row == target_row && col == target_col) {
            return count;
        }
        if (row + 1 < matrix.size() && matrix[row + 1][col] && visit[row + 1][col]) {
            visit[row + 1][col] = false;
            que.push(make_pair(row + 1, col));
            count.push(curCount + 1);
        }
        if (row - 1 >= 0 && matrix[row - 1][col] && visit[row - 1][col]) {
            visit[row - 1][col] = false;
            que.push(make_pair(row - 1, col));
            count.push(curCount + 1);
        }
        if (col + 1 < matrix[0].size() && matrix[row][col + 1] && visit[row][col + 1]) {
            visit[row][col + 1] = false;
            que.push(make_pair(row, col + 1));
            count.push(curCount + 1);
        }
        if (col- 1 >= 0 && matrix[row][col - 1] && visit[row][col - 1]) {
            visit[row][col - 1] = false;
            que.push(make_pair(row, col - 1));
            count.push(curCount + 1);
        }
    }
    
    return -1;
}
Q: How to std::cout some sentences before main() function.
A : constructor of a global object will be called before main()
 class Object {
public:
  Object();
};

Object::Object() {
  cout << "my message\n";
}

// define a global object somewhere in .cc or .cxx or .cpp
Object obj;

int main()
{
}

Friday, May 3, 2013

Day 25, 2, 3, Add Two Numbers, Longest Substring Without Repeating Characters

Add Two Numbers
You are given two linked lists representing two non-negative numbers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
-----------------------------------------
Solution #1, No extra space
/**
 * Definition for binary tree/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *addTwoNumbers(ListNode *l1, ListNode *l2) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        bool increm = false;
        ListNode *re = l1;
        ListNode *pre = NULL; // for adding extra node
        while (l1 != NULL && l2 != NULL) {
            int sum = l1->val + l2->val;
            if (increm) {
                sum++;
                increm = false;
            }
            if (sum > 9) {
                l1->val = sum%10;
                increm = true;
            }else {
                l1->val = sum;
            }
            pre = l1;
            l1 = l1->next;
            l2 = l2->next;
        }
        if (l2 != NULL) {
            pre->next = l2;
            l1 = l2;
        }
        if (l1 != NULL) {
            while (increm && l1 != NULL ) {
                if ((l1->val == 9)) {
                    l1->val = 0;
                    pre = l1;
                    l1 = l1->next;
                }else {
                    l1->val = l1->val + 1;
                    increm = false;
                }
            }
        }
        // extra node
        if (increm) {
            pre->next = new ListNode(1);
        }
        return re;
    }
};

Update on July-10-2015
Solution #2, 3点可以优化代码
#1 carry可以用来当sum用
#2 loop的终止条件配合loop内的判断
#3 dummy node
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode *dummy = new ListNode(0), *itr = dummy;
        int carry = 0;
        while (l1 != NULL || l2 != NULL) {
            if (l1 != NULL) {
                carry += l1->val;
                l1 = l1->next;
            }
            if (l2 != NULL) {
                carry += l2->val;
                l2 = l2->next;
            }
            
            ListNode *node = new ListNode(carry % 10);
            carry /= 10;
            itr->next = node;
            itr = itr->next;
        }
        if (carry) {
            ListNode *node = new ListNode(1);
            itr->next = node;
        }
        
        return dummy->next;
    }
};

Longest Substring Without Repeating Characters
Given a string, find the length of the longest substring without repeating characters. For example, the longest substring without repeating letters for "abcabcbb" is "abc", which the length is 3. For "bbbbb" the longest substring is "b", with the length of 1.
--------------------------------------
O(n), two pointers:
set flag[start++] to false, flag[end++] to true
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        bool matrix[256] = { false };
        int start=0;
        int maxSub=0, curMax=0;
        for (int i=0;i<s.length();i++) {
            if (matrix[s[i]]) {
                maxSub = max(maxSub,curMax);
                while (s[start] != s[i]) {
                    matrix[s[start]] = false;
                    start++;
                    curMax--;
                }
                start++;
            }else {
                matrix[s[i]] = true;
                curMax++;
            }
        }
        return max(maxSub,curMax);
    }
};

Day 24, 125, 129, Valid Palindrome, Sum Root to Leaf Numbers

Best Time to Buy and Sell Stock
Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases.
For example,
"A man, a plan, a canal: Panama" is a palindrome.
"race a car" is not a palindrome.
Note:
Have you consider that the string might be empty? This is a good question to ask during an interview.
For the purpose of this problem, we define empty string as valid palindrome.
-----------------------------------------------------------
class Solution {
public:
    bool isPalindrome(string s) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        string str="";
        for (int i=0;i<s.length();i++) {
            if (isalnum(s[i])) {
                str += tolower(s[i]);
            }
        }
        int length = str.length();
        for (int i=0;i<length/2;i++) {
            if (str[i] != str[length - i-1]) {
                return false;
            }
        }
        return true;
    }
};
Update on Jan-16-2015
constant space
class Solution {
public:
    bool isPalindrome(string s) {
        int left = 0;
        int right = s.length();
        
        while (left < right) {
            if (isalnum(s[left]) && isalnum(s[right])) {
                if (s[left] == s[right] 
                    || s[left] + 32 == s[right] 
                    || s[left] == s[right] + 32) {
                    left++;
                    right--;
                }else {
                    return false;
                }
                
            }else if (!isalnum(s[left])) {
                left++;
            }else if (!isalnum(s[right])) {
                right--;
            }
        }
        return true;
    }
};

Sum Root to Leaf Numbers
Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number.
An example is the root-to-leaf path 1->2->3 which represents the number 123.
Find the total sum of all root-to-leaf numbers.
For example,
    1
   / \
  2   3
The root-to-leaf path 1->2 represents the number 12.
The root-to-leaf path 1->3 represents the number 13.
Return the sum = 12 + 13 = 25.
 -----------------------------------------------------------------
/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    void leef (TreeNode *root, int pathSum, int & sum) {
        int sumL = pathSum, sumR = pathSum;
        if (root->left != NULL) {
            sumL = sumL*10 + root->left->val;
            leef(root->left,sumL,sum);
        }
        if (root->right != NULL) {
            sumR = sumR*10 + root->right->val;
            leef(root->right,sumR,sum);
        }
        if (root->left == NULL && root->right == NULL) {
            sum += pathSum;
        }
    }

    int sumNumbers(TreeNode *root) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if (root == NULL) return 0;
        int sum=0;
        leef(root,root->val,sum);
        return sum;
    }
};