Showing posts with label two pointers. Show all posts
Showing posts with label two pointers. Show all posts

Friday, January 3, 2014

Day 73, ##, Reorder List, Binary Tree Preorder Traversal, Binary Tree Postorder Traversal, Insertion Sort List

Reorder List
Given a singly linked list L: L0L1→…→Ln-1Ln,
reorder it to: L0LnL1Ln-1L2Ln-2→…
You must do this in-place without altering the nodes' values.
For example,
Given {1,2,3,4}, reorder it to {1,4,2,3}.
------------------------------------------------------------
3 steps:
1) divide list in half
2) reverse the second half
3) merge/reorder
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList (ListNode *head) {
        if (head == NULL || head->next == NULL) return head;
        ListNode *itr = head;
        head = NULL;
        while (itr != NULL) {
            ListNode *tmp = itr->next;
            itr->next = head;
            head = itr;
            itr = tmp;
        }
        return head;
    }

    void reorderList(ListNode *head) {
        // find the second half
        if (head == NULL || head->next == NULL) return;
        ListNode *slow = head, *fast = head;
        
        while (fast != NULL) {
            fast = fast->next;
            if (fast!= NULL) {
                slow = slow->next;
                fast = fast->next;
            }
        }
        
        // reverse
        ListNode *head2 = slow->next;
        slow->next = NULL;
        head2 = reverseList(head2);
        
        // merge
        ListNode *cur = head;
        while (head2 != NULL) {
            ListNode *temp = cur->next;
            ListNode *temp2 = head2->next;
            cur->next = head2;
            cur = temp;
            head2->next = cur;
            head2 = temp2;            
        }
    }
};
Solution#2, recursive
(to do)

Binary Tree Preorder Traversal
Given a binary tree, return the preorder traversal of its nodes' values.
For example:
Given binary tree {1,#,2,3},

   1
    \
     2
    /
   3
return [1,2,3].
Note: Recursive solution is trivial, could you do it iteratively?
------------------------------------------------------------
Similar to #94 Binary Tree Inorder Traversal
using stack, push right node first, then left node
/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> preorderTraversal(TreeNode *root) {
        vector<int> ret;
        stack<TreeNode*> s;
        s.push(root);
        while (!s.empty()) {
            TreeNode* node = s.top();
            s.pop();
            if (node == NULL) continue;
            ret.push_back(node->val);
            s.push(node->right);
            s.push(node->left);
        }
        return ret;
    }
};
Binary Tree Postorder Traversal
Given a binary tree, return the postorder traversal of its nodes' values.
For example:
Given binary tree {1,#,2,3},

   1
    \
     2
    /
   3
return [3,2,1].
Note: Recursive solution is trivial, could you do it iteratively?
----------------------------------------------------
Solution #1, with visited flag
Similar to #94 Binary Tree Inorder Traversal
/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> postorderTraversal(TreeNode *root) {
        vector<int> ret;
        stack<pair<TreeNode*,bool> > s;
        s.push(make_pair(root,false));
         
        while (!s.empty()) {
            pair<TreeNode*,bool> p = s.top();
            if (p.first != NULL) {
                if (p.second == false) {
                    s.top().second = true;
                    s.push(make_pair(p.first->right,false));
                    s.push(make_pair(p.first->left,false));
                }else {
                    ret.push_back(p.first->val);
                    s.pop();
                }
            }else {
                s.pop();
            }
        }
        return ret;
    }
};
Solution #2, without visited flag
/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> postorderTraversal(TreeNode *root) {
        vector<int> ret;
        if (root == NULL) return ret;
        stack<TreeNode*> s;
        s.push(root);
        TreeNode* pre = NULL;
        
        while (!s.empty()) {
            TreeNode* cur = s.top();
            // traverse down the tree
            if (!pre || pre->left == cur || pre->right == cur) {
                if (cur->left != NULL) {
                    s.push(cur->left);
                }else if (cur->right != NULL) {
                    s.push(cur->right);
                }else {
                    // reach a leaf node
                    ret.push_back(cur->val);
                    s.pop();
                }
            }
            else if (cur->left == pre) {
                // traverse from the left
                if (cur->right != NULL) {
                    s.push(cur->right);
                }else {
                    ret.push_back(cur->val);
                    s.pop();
                }
            }else if (cur->right == pre) {
                // from the right
                ret.push_back(cur->val);
                s.pop();
            }
            
            pre = cur;
        }
        
        return ret;
    }
};
Solution#3, using two stacks
Further reading
http://leetcode.com/2010/10/binary-tree-post-order-traversal.html
/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> postorderTraversal(TreeNode *root) {
        stack<TreeNode*> roots;
        stack<TreeNode*> rights;
        vector<int> rt;
        
        while (root != NULL || !roots.empty() || !rights.empty()) {
            if (root != NULL) {
                roots.push(root);
                if (root->right != NULL) {
                    rights.push(root->right);
                }
                root = root->left;
                
            }else {
                if (!rights.empty() && roots.top()->right == rights.top()) {
                    root = rights.top();
                    rights.pop();
                    
                }else {
                    rt.push_back(roots.top()->val);
                    roots.pop();
                }
            }
        }
        
        return rt;
    }
};
Update on Feb-1st-2015
post-order is left -> right -> root, we can traverse the tree backwards: root -> right -> left, then reverse the result 
class Solution {
public:
    vector<int> postorderTraversal(TreeNode *root) {
        stack<TreeNode*> st;
        vector<int> rt;
        if (root == NULL) return rt;
        
        st.push(root);
        while (!st.empty()) {
            TreeNode *node = st.top();
            st.pop();
            rt.push_back(node->val);
            if (node->left != NULL) {
                st.push(node->left);
            }
            if (node->right != NULL) {
                st.push(node->right);
            }
        }
        
        reverse(rt.begin(),rt.end());
        return rt;
    }
};

Insertion Sort List
Sort a linked list using insertion sort.
---------------------------------------------------
wiki
http://en.wikipedia.org/wiki/Insertion_sort

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *insertionSortList(ListNode *head) {
        ListNode *dummy = new ListNode(INT_MIN);
        dummy->next = head;
        ListNode *itr = head, *sorted = dummy;
        
        while (itr != NULL) {
            if (itr->val >= sorted->val) {
                itr = itr->next;
                sorted = sorted->next;
            }else {
                ListNode *n = dummy;
                while (n->next->val <= itr->val) {
                    n = n->next;
                }
                
                ListNode *tmp = itr->next;
                ListNode *tmp2 = n->next;
                n->next = itr;
                itr->next = tmp2;
                sorted->next = tmp;
                
                itr = tmp;
            }
        }
        return dummy->next;
    }
};

Thursday, January 2, 2014

Day 72, ##, Word Break, Word Break II, Linked List Cycle, Linked List Cycle II

Word Break
Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separated sequence of one or more dictionary words.
For example, given
s = "leetcode",
dict = ["leet", "code"].
Return true because "leetcode" can be segmented as "leet code".
-----------------------------------------------------------------------
Just DP
dp[i] has the boolean value that means if string[i : n] can be partitioned according to our dictionary. Hence dp[len] represents the empty string and dp[0] is the answer we are looking for.
For each iteration in the inner for loop, we add a new cut at index j to string[i : n], in whcih string[i : j] has never checked before but string[j + 1 : n](result is in dp[j + 1]) has been known since the previous iteration in outer loop.
class Solution {
public:
    bool wordBreak(string s, unordered_set<string> &dict) {
        int len = s.length();
        vector<bool> dp(len + 1,false);
        dp[len] = true;
        
        for (int i = len - 1; i >= 0; i--) {
            for (int j = i; j < len; j++) {
                string str = s.substr(i,j - i + 1);
                if (dict.find(str) != dict.end() && dp[j + 1]) {
                    dp[i] = true;
                    break;
                }
            }
        }
        return dp[0];
    }
};

Java, memoization. Updated on Jun-25th-2018
class Solution {
    public boolean wordBreak(String s, List wordDict) {
        Map m = new HashMap<>();
        return dfs(s, new HashSet(wordDict), m);
    }
    
    private boolean dfs(String s, Set dic, Map m) {
        if (s.length() == 0) return true;
        
        for (int i = 0; i < s.length(); i++) {
            String sub = s.substring(0, i + 1);
            String nextSub = s.substring(i + 1);
            
            if (!dic.contains(sub)) {
                continue;
            }
            
            boolean next;
            if (m.containsKey(nextSub)) {
                next = m.get(nextSub);
            }else {
                next = dfs(s.substring(i + 1), dic, m);
            }
            
            if (next) return true;
        }
        
        m.put(s, false);
        return false;
    }
}

ToDo: 有意思的bfs,把每个单词当作是node,queue里可以存index https://leetcode.com/problems/word-break/discuss/43797/A-solution-using-BFS

Word Break II
Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where each word is a valid dictionary word.
Return all such possible sentences.
For example, given
s = "catsanddog",
dict = ["cat", "cats", "and", "sand", "dog"].
A solution is ["cats and dog", "cat sand dog"].
-----------------------------------------------
Based on Word Break, add one more DP to store all possible partition at current index
因为LC加了新的test case,以下代码得加一段word break I的代码,来先检测s是否能被分解
class Solution {
public:
    vector<string> wordBreak(string s, unordered_set<string> &dict) {
        // Note: The Solution object is instantiated only once and is reused by each test case.
         int len = s.length();
        vector<bool> dp(len + 1,false);
        vector<vector<string> > dp2(len + 1,vector<string>());
        dp2[len].push_back("");
        dp[len] = true;
        
        for (int i = len - 1; i >= 0; i--) {
            for (int j = i; j < len; j++) {
                string str = s.substr(i,j - i + 1);
                if (dict.find(str) != dict.end() && dp[j + 1]) {
                    dp[i] = true;
                    for (int index = 0; index < dp2[j + 1].size(); index++) {
                        string empty = "";
                        if (j + 1 != len) empty = " "; 
                        string n = str + empty + dp2[j + 1][index]; 
                        dp2[i].push_back(n);
                    }
                }
            }
        }
        return dp2[0];
    }
};

dfs,减枝之后也能过OJ
class Solution {
public:
    void dfs(vector<string> &rt, string s, int index,string cur, unordered_set<string>& wordDict) {
        if (index == s.length()) {
            rt.push_back(cur);
            return;
        }
         
         bool notFound = true;
            for (int i = s.size() - 1; i >= index; --i) {   
                if (wordDict.find(s.substr(i)) != wordDict.end()) {
                    notFound = false;
                    break;
                } 
            }
            if (notFound) { return ; }
        
        for (int i = index; i < s.length(); i++) {
            string sub = s.substr(index,i - index + 1);
            if (wordDict.find(sub) != wordDict.end()) {
                string t = cur;
                if (t.length() == 0) {
                    t = sub;
                }else {
                    t += " " + sub;
                }
                dfs(rt,s,i + 1,t,wordDict);
            }
        }
    }

    vector<string> wordBreak(string s, unordered_set<string>& wordDict) {
        vector<string> rt;
        dfs(rt,s,0,"",wordDict);
        return rt;
    }
};

Java,在Word Break I的基础上进行修改的dfs. Updated on Jun-26th-2018
class Solution {
    public List wordBreak(String s, List wordDict) {
        return dfs(s, new HashSet(wordDict), new HashMap>());
    }
    
    private List dfs(String s, Set dic, Map> m) {
        if (s.length() == 0) return new ArrayList<>();

        List rt = new ArrayList<>();

        for (int i = 0; i < s.length(); i++) {
            String sub = s.substring(0, i + 1);
            String nextSub = s.substring(i + 1);

            if (!dic.contains(sub)) {
                continue;
            }

            List next;
            if (m.containsKey(nextSub)) {
                next = m.get(nextSub);
            }else {
                next = dfs(s.substring(i + 1), dic, m);               
            }
            
            for (String can : next) {
                rt.add(sub + " " + can);
            }
            
            if (i == s.length() - 1) {
                rt.add(sub);    
            }
        }

        m.put(s, rt);
        return rt;
    }
}

Todo: 写一个iterate版本的

Linked List Cycle
Given a linked list, determine if it has a cycle in it.
Follow up:
Can you solve it without using extra space?
--------------------------------------------------------------
two pointers, one traverses twice as fast as the other
return true if they meet 
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool hasCycle(ListNode *head) {
        if (head == NULL) return false;
        ListNode *slow = head, *fast = head->next;
        bool flag = false;
        while (fast != NULL) {
            if (fast == slow) {
                flag = true;
                break;
            }
            
            fast = fast->next;
            if (fast != NULL) {
                slow = slow->next;
                fast = fast->next;
            }
        }
        return flag;
    }
};
Linked List Cycle II
Given a linked list, return the node where the cycle begins. If there is no cycle, return null.
Follow up:
Can you solve it without using extra space?
-----------------------------------------------------------------
Floyd's cycle-finding algorithm
Note: as opposed to Linked List Cycle
1) fast is initialized to head, not head->next
2) if (fast == slow) is executed after pointers've been moved
Update Dec-30th-2014
假设 x 为起跑线到loop的起点的距离,y为该起点到两个指针相遇点的距离,z为该点到起点的距离,则loop的长度 L = y + z
m 为慢指针在相遇时跑过的距离: m = x + y
n 为快指针在相遇时跑过的距离: n = x + y + k * L, k > 0
已知 2m = n
2(x + y) = x + y + k * L
x = k * L - y
x = (k - 1) * L + z
证毕

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        if (head == NULL) return false;
        ListNode *slow = head, *fast = head;
        bool flag = false;
        while (fast != NULL) {
            fast = fast->next;
            if (fast != NULL) {
                slow = slow->next;
                fast = fast->next;
            }
            
            if (fast == slow) {
                flag = true;
                break;
            }
        }
        if (!flag) return NULL;
        
        slow = head;
        while (slow != fast) {
            slow = slow->next;
            fast = fast->next;
        }
        
        return slow;
    }
};

Tuesday, December 24, 2013

Day 64, #76, Minimum Window Substring

Minimum Window Substring
Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n).
For example,
S = "ADOBECODEBANC"
T = "ABC"

Minimum window is "BANC".
Note:
If there is no such window in S that covers all characters in T, return the emtpy string "".
If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in S.
-----------------------------------------------------------------------------

## 注意第14行,当前char如果为不需要时,直接跳过。第22行类似。围绕着t里面的字符
## 当发现至少存在一个符合substring时,count一直保持为0

O(n)
------ Explanation here ---------
class Solution {
public:
    string minWindow(string s, string t) {
        vector<int> needed(256,0);
        vector<int> owned(256,0);
        for (int i = 0; i < t.length(); i++) {
            needed[t[i]]++; 
        }
        
        int count = t.length();
        int start = 0;
        string rt = "";
        for (int i = 0; i < s.length(); i++) {
            if (needed[s[i]] == 0) continue;
            owned[s[i]]++;
            if (owned[s[i]] <= needed[s[i]]) {
                if (count == t.length()) start = i;
                count--;
            }
            
            if (count == 0) {
                while (needed[s[start]] == 0 || owned[s[start]] > needed[s[start]]) {
                    if (owned[s[start]] > needed[s[start]]) {
                        owned[s[start]]--;
                    }
                    start++;
                }
                if (rt == "" || rt.length() > i - start + 1) {
                    rt = s.substr(start,i - start + 1);
                }
            }
        }
        
        return rt;
    }
};

Java版,总体思路一样,实现上有一点出入
ToDo 扩展阅读,解决所有substring的通用方法:https://leetcode.com/problems/minimum-window-substring/discuss/26808/Here-is-a-10-line-template-that-can-solve-most-'substring'-problems

class Solution {
    public String minWindow(String s, String t) {
        int[] needed = getMap(t);
        int[] sofar = new int[256];
        int count = t.length();
        
        int start = -1;
        String rt = "";
        for (int i = 0; i < s.length(); i++) {
            int c = s.charAt(i);
            sofar[c]++;
            if (needed[c] > 0 && sofar[c] <= needed[c]) {
                count--;
                if (start == -1) start = i;
            }
            while (start != -1 && sofar[s.charAt(start)] > needed[s.charAt(start)]) {
                sofar[s.charAt(start)]--;
                start++;
            }
            if (count == 0 && (i - start + 1 < rt.length() || rt == "")) {
                rt = s.substring(start,i + 1);
            }
        }
            
        return rt;
    }
    
    private int[] getMap(String t) {
        int[] map = new int[256];
        for (int i = 0; i < t.length(); i++) {
            map[t.charAt(i)]++;
        }
        
        return map;
    }
}

Monday, December 23, 2013

Day 63, #72, #75, Edit Distance, Sort Colors

Edit Distance
Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.)
You have the following 3 operations permitted on a word:
a) Insert a character
b) Delete a character
c) Replace a character
------------------------------------------------------------------------------------
Further reading:
Wagner–Fischer algorithm
Edit distance
http://www.youtube.com/watch?v=ocZMDMZwhCY
class Solution {
public:
    int minDistance(string word1, string word2) {
       int m = word1.length();
       int n = word2.length();
       
       vector<vector<int> > dp(m + 1,vector<int>(n + 1,0));
       
       // the distance of any first string to an empty second string
       for (int i = 0; i < m + 1; i++) {
           dp[i][0] = i;
       }
       
       // the distance of any second string to an empty first string
       for (int i = 0; i < n + 1; i++) {
           dp[0][i] = i;
       }
       
       for (int i = 1; i < m + 1; i++) {
           for (int j = 1; j < n + 1; j++) {
               if (word1[i - 1] == word2[j - 1]) {
                   dp[i][j] = dp[i - 1][j - 1]; 
               }else {
                   int temp = min(dp[i][j - 1],dp[i - 1][j]);
                   dp[i][j] = min(temp,dp[i - 1][j - 1]) + 1;
                   
               }
           }
       }
       return dp[m][n];
    }
};
Update on Nov-16-2014
if word[i] !=  word2[j] the cost from [i:end] to [j:end] is the minimal among

  1. cost of insert + [i:end] [j - 1:end]
  2. cost of delete + [i - 1:end] [j:end]
  3. cost of replace + [i:end] [j:end]

if word1[i] == word2[j], then the distance of [i:end] and [j:end] is [i-1:end] and [j-1:end]
Improvement on this algorithm - Wagner–Fischer algorithm

O(n) space
class Solution {
public:
    int minDistance(string word1, string word2) {
        int m = word1.length(),n = word2.length();
        if (m == 0) return n;
        if (n == 0) return m;
        vector<int> dp(n + 1,0);
        vector<int> pre(n + 1,0);
        for (int i = 0; i <= n; i++) {
            pre[i] = i;
        }
        
        for (int i = 1; i <= m; i++) {
            dp[0] = i;
            
            for (int j = 1; j <= n; j++) {
                if (word1[i - 1] == word2[j - 1]) {
                    dp[j] = pre[j - 1];
                }else {
                    dp[j] = 1 + min(pre[j],min(dp[j - 1],pre[j - 1]));
                }
            }
            pre = dp;
        }
        
        return dp[n];
    }
};

递归:有重复子问题,所以用DP
int minDistance(string s1,string s2,int i,int j) {
    if (i == s1.length() && j == s2.length()) return 0;
    if (i == s1.length()) return s2.length() - j + 1;
    if (j == s2.length()) return s1.length() - i + 1;
    
    if (s1[i] == s2[j]) return edit(s1,s2,i + 1,j + 1);
    return 1 + min(edit(s1,s2,i + 1, j + 1),min(edit(s1,s2,i + 1,j),edit(s1,s2,i,j + 1)));
}

Sort Colors
Given an array with n objects colored red, white or blue, sort them so that objects of the same color are adjacent, with the colors in the order red, white and blue.
Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.
Note:
You are not suppose to use the library's sort function for this problem.
Follow up:
A rather straight forward solution is a two-pass algorithm using counting sort.
First, iterate the array counting number of 0's, 1's, and 2's, then overwrite array with total number of 0's, then 1's and followed by 2's.
Could you come up with an one-pass algorithm using only constant space?---------------------------------------------------------
One pass
class Solution {
public:
    void sortColors(int A[], int n) {
        int itr = 0;
        int ptrZero = 0;
        int ptrTwo = n - 1;
        while (itr <= ptrTwo) {
            if (A[itr] == 1) {
                itr++;
            }else if (A[itr] == 0) {
                swap(A[itr],A[ptrZero]);
                ptrZero++;
                if (ptrZero >= itr) {
                    itr++;
                }
            }else if (A[itr] == 2) {
                swap(A[itr],A[ptrTwo]);
                ptrTwo--;
            }
        }
    }
};

Update on Jan-26-2015
re-factoried
class Solution {
public:
    void swap(int A[], int i, int j) {
        int temp = A[i];
        A[i] = A[j];
        A[j] = temp;
    }

    void sortColors(int A[], int n) {
        int start = 0;
        int end = n - 1;
        int itr = 0;
        
        while (itr <= end) {
            if (A[itr] == 0) {
                swap(A,itr,start);
                start++;
                itr++;
            }else if (A[itr] == 2) {
                swap(A,itr,end);
                end--;
            }else {
                itr++;
            }
        }
    }
};

Wednesday, December 18, 2013

Day 58, #42, #43, #55, Trapping Rain Water, Multiply Strings, Jump Game II

Trapping Rain Water
Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.
For example,
Given [0,1,0,2,1,0,1,3,2,1,2,1], return 6.


The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped. Thanks Marcos for contributing this image!
-----------------------------------------------------------------------------------
O(n) solution. for each bar, find the max height bar on the left and right. then for this bar it can hold min(max_left, max_right) - height
class Solution {
public:
    int trap(int A[], int n) {
        vector<int> leftMax(n,0);
        vector<int> rightMax(n,0);
        
        // get left max for each element
        for (int i = 1; i < n; i++) {
            leftMax[i] = max(leftMax[i - 1],A[i - 1]);
        }
        
        // get right max for each element
        for (int i = n - 2; i >= 0; i--) {
            rightMax[i] = max(rightMax[i + 1], A[i + 1]);
        }
        
        int sum = 0;
        for (int i = 0; i < n; i++) {
            int water = min(leftMax[i],rightMax[i]) - A[i]; 
            if (water > 0) {
                sum += water; 
            }
        }
        return sum;
    }
};
Update on Nov-6th-2014
come back
Solution #2, if leftMax < rightMax, leftIndex can contain (leftMax - A[leftIndex]) water, regardless what it looks like between leftIndex and rightIndex
class Solution {
public:
    int trap(int A[], int n) {
        int sum = 0;
        int leftMax = 0, rightMax = 0;
        int leftIndex = 0, rightIndex = n - 1;
        
        while (leftIndex <= rightIndex) {
            leftMax = max(leftMax,A[leftIndex]);
            rightMax = max(rightMax,A[rightIndex]);
            if (leftMax < rightMax) {
                sum += leftMax - A[leftIndex];
                leftIndex++;
            }else {
                sum += rightMax - A[rightIndex];
                rightIndex--;
            }
        }
        
        return sum;
    }
};
Multiply Strings
Given two numbers represented as strings, return multiplication of the numbers as a string.
Note: The numbers can be arbitrarily large and are non-negative.
--------------------------------------
Multiply numbers using straightforward math
class Solution {
public:
    string multiply(string num1, string num2) {
        int len1 = num1.length(), len2 = num2.length();
        string sum(len1 + len2,'0');
      
        for (int i = len1 - 1; i >= 0; i--) {
            int carry = 0;
            for (int j = len2 - 1; j >= 0; j--) {
                int cur = (sum[i + j + 1] - '0') + carry + (num1[i] - '0') * (num2[j] - '0');
                sum[i + j + 1] = cur % 10 + '0';
                carry = cur / 10;
            }
            sum[i] += carry;   
        }
        
        int start = 0;
        while (sum[start] == '0') {
            start++;
        }
        if (start == sum.length()) return "0";
        return sum.substr(start);
    }
};
Jump Game II
Given an array of non-negative integers, you are initially positioned at the first index of the array.
Each element in the array represents your maximum jump length at that position.
Your goal is to reach the last index in the minimum number of jumps.
For example:
Given array A = [2,3,1,1,4]
The minimum number of jumps to reach the last index is 2. (Jump 1 step from index 0 to 1, then 3 steps to the last index.)
---------------------------------------------------------------------------
Greedy, the point of this question is to find the largest distance with minimum steps
Every time 'i' passes curMax, increment step


class Solution {
public:
    int jump(int A[], int n) {
        int curMax = 0, newMax = 0;
        int step = 0;
        for (int i = 0; i < n; i++) {
            if (i > curMax) {
                // set up new max from old steps
                curMax = newMax;
                step++;
            }
            newMax = max(newMax,i + A[i]); // this line should be placed after if condition, 'cause new step has been made
        }
        return step;
    }
};
Update on Nov-7th-2014
a slightly different version, handles the case where the goal cannot be reached
class Solution {
public:
    int jump(int A[], int n) {
        if (n == 1) return 0;
        int step = 1;
        int currentReach = A[0];
        int maxCanReach = A[0];
        
        for (int i = 1; i < n; i++) {
            if (i > currentReach) {
                // to handle cases where the end cannot be reached
                if (currentReach == maxCanReach) {
                    return -1;
                }
                step++;
                currentReach = maxCanReach;
            }
            maxCanReach = max(maxCanReach,i + A[i]);
        }
        
        return step;
    }
};

Friday, November 22, 2013

Day 53, 28, Implement strStr()

Implement strStr()
Implement strStr().
Returns a pointer to the first occurrence of needle in haystack, or null if needle is not part of haystack.
------------------------------------------------- 
KMP, O(n),
class Solution {
public:
    vector<int> computePrefixTable(string pattern) {
        int m = pattern.length();
        vector<int> table(m,0);
        int matchedLength = 0;
        
        for (int i = 1; i < m; i++) {
            // until find the next char at matchedLength is equal to char at i
            // or matchedLength is zero
            while (matchedLength > 0 && pattern[matchedLength] != pattern[i]) {
                matchedLength = table[matchedLength - 1];
            }
            if (pattern[matchedLength] == pattern[i]) {
                matchedLength++;
            }
            table[i] = matchedLength;
        }
        
        return table;
    }
    
    int KMP(string source, string pattern) {
        int n = source.length();
        int m = pattern.length();
        vector<int> table = computePrefixTable(pattern);
        int matchedLength = 0;
        
        for (int i = 0; i < n; i++) {
            while (matchedLength > 0 && pattern[matchedLength] != source[i]) {
                matchedLength = table[matchedLength - 1];
            }
            
            if (pattern[matchedLength] == source[i]) {
                matchedLength++;
            }
            if (matchedLength == m) {
                return i - m + 1;
            }
        }
        
        return -1;
    }

    int strStr(string haystack, string needle) {
        if (needle == "") return 0;
        if (haystack == "") return -1;
        return KMP(haystack,needle);
    }
};
Solution #2 O(m*n), improved brute force
class Solution {
public:
    char *strStr(char *haystack, char *needle) {
        // IMPORTANT: Please reset any member data you declared, as
        // the same Solution instance will be reused for each test case.
        if (*needle == NULL) return haystack;
        if (!*haystack) return NULL;
        char* adv = haystack;
        char* temp = needle;
        while (*++temp) {
            adv++;
        }
        
        while (*adv != NULL) {
            char* itr1 = haystack;
            char* itr2 = needle;
            while (*itr1 && *itr2 && *itr1 == *itr2) {
                itr1++;
                itr2++;
            }
            if (!*itr2) return haystack;
            haystack++;
            adv++;
        }
        return NULL;
    }
};

Wednesday, August 28, 2013

Day 42, #92, #109, Reverse Linked List II, Convert Sorted List to Binary Search Tree

Reverse Linked List II
Reverse a linked list from position m to n. Do it in-place and in one-pass.
For example:
Given 1->2->3->4->5->NULL, m = 2 and n = 4,
return 1->4->3->2->5->NULL.
Note:
Given m, n satisfy the following condition:
1 ? m ? n ? length of list.
----------------------------------------
lets say m = 3, n = 5
1             2              3             4             5            6
|              |                |                             |
head      left           tail                     newHead

/* Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *reverseBetween(ListNode *head, int m, int n) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        ListNode *newHead = NULL, *itr = head,*left = NULL,*tail;
        // move to m-th node
        for (int i = 1; i < m; i++) {
            left = itr;
            itr = itr->next;
        }
        tail = itr;
        // move to n-th node
        for (int i = m; i <= n; i++) {
            ListNode *temp = itr->next;
            itr->next = newHead;
            newHead = itr;
            itr = temp;
        }
        tail->next = itr;
        if (m == 1) {
            return newHead;
        }
        left->next = newHead;
        return head;
    }
};
Convert Sorted List to Binary Search Tree
Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST.
--------------------------------------------------------------------------
Further reading:
http://leetcode.com/2010/11/convert-sorted-list-to-balanced-binary.html
http://www.geeksforgeeks.org/sorted-linked-list-to-balanced-bst/
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* constructTree (ListNode *&list,int start, int end) {
        if (start > end) {
            return NULL;
        }
        int mid = start + (end - start) / 2;
        TreeNode *left = constructTree(list,start,mid - 1);
        TreeNode *root = new TreeNode(list->val);
        root->left = left;
        list = list->next;
        root->right = constructTree(list,mid + 1, end);
        return root;
    }


    TreeNode *sortedListToBST(ListNode *head) {
        int n = 0;
        ListNode *itr = head;
        while (itr != NULL ) {
            n++;
            itr = itr->next;
        }
        return constructTree(head,0,n-1);
    }
};
Update Nov-21-2014
Bottom up solution. For each node, build the left child -> root -> right child, follow the in order sequence

Thursday, July 11, 2013

Day 40, 86 Partition List

Partition List
Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x.
You should preserve the original relative order of the nodes in each of the two partitions.
For example,
Given 1->4->3->2->5->2 and x = 3,
return 1->2->2->4->3->5.
---------------------------------------------------------------------
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *partition(ListNode *head, int x) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if (head == NULL) return head;
        ListNode *leftHead = NULL, *rightHead = NULL, *end;
        ListNode ** before = &leftHead, **after = &rightHead;
        while (head != NULL) {
            if (head->val >= x) {
                *after = head;
                after = &(head->next);
            }else {
                *before = head;
                before = &(head->next);
            }
            // use end to break the new attached node from the original list
            end = head;
            head = head->next;
            end->next = NULL;
        }
        *before = rightHead; // connect two lists
        return leftHead;
    }
};
Update on Sep-19-2014 
Without double-pointer
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *partition(ListNode *head, int x) {
        ListNode *head1 = NULL, *head2 = NULL,*tail1 = NULL,*tail2 = NULL;
        
        while (head != NULL) {
            if (head->val < x) {
                if (head1 == NULL) {
                    head1 = head;
                    tail1 = head;
                }else {
                    tail1->next = head;
                    tail1 = tail1->next;
                }
            }else {
                
                if (head2 == NULL) {
                    head2 = head;
                    tail2 = head;
                }else {
                    tail2->next = head;
                    tail2 = tail2->next;
                }
            }
            head = head->next;
        }
        
        // merge
        if (tail1 != NULL) tail1->next = head2;
        if (tail2 != NULL) tail2->next = NULL;
        if (head1 == NULL) return head2;
        return head1;
    }
};

Sunday, July 7, 2013

Day 39, 79, 82 Word Search, Remove Duplicates from Sorted List II

Word Search
Given a 2D board and a word, find if the word exists in the grid.
The word can be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once.
For example,
Given board =
[
  ["ABCE"],
  ["SFCS"],
  ["ADEE"]
]
word = "ABCCED", -> returns true,
word = "SEE", -> returns true,
word = "ABCB", -> returns false.
----------------------------------------------
class Solution {
public:
    bool searchWord (vector<vector<char> > &board, string word, int cur, int row, int col,vector<vector<bool> > &mapping) {
        int rowSize = board.size();
        int colSize = board[0].size();
        if (word.size() == cur) return true; 
        if (word.size() > cur) {
            if (row > 0 && mapping[row-1][col] && word[cur] == board[row-1][col]) {
                mapping[row-1][col] = false;
                if (searchWord(board,word,cur+1,row-1,col,mapping)) {
                    return true;
                }
                mapping[row-1][col] = true;
            }
            if (row < rowSize-1 && mapping[row+1][col] && word[cur] == board[row+1][col]) {
                mapping[row+1][col] = false;
                if (searchWord(board,word,cur+1,row+1,col,mapping)) {
                    return true;
                }
                mapping[row+1][col] = true;
            }
            if (col < colSize-1 && mapping[row][col+1] && word[cur] == board[row][col+1]) {
                mapping[row][col+1] = false;
                if (searchWord(board,word,cur+1,row,col+1,mapping)) {
                    return true;
                }
                mapping[row][col+1] = true;
            }
            if (col > 0 && mapping[row][col-1] && word[cur] == board[row][col-1]) {
                mapping[row][col-1] = false;
                if (searchWord(board,word,cur+1,row,col-1,mapping)) {
                    return true;
                }
                mapping[row][col-1] = true;
            }
        }
        return false;
    }

    bool exist(vector<vector<char> > &board, string word) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        int rowSize = board.size();
        int colSize = board[0].size();
        vector<vector<bool>> mapping(rowSize, vector<bool>(colSize, true));
        for (int i=0;i<rowSize;i++) {
            for (int j=0;j<colSize;j++) {
                if (board[i][j] == word[0]) {
                    mapping[i][j] = false;
                    if (searchWord(board,word,1,i,j,mapping)) return true;
                    mapping[i][j] = true;
                }
            }
        }
        return false;
    }
};

更新
class Solution {
public:
    bool searchWord(vector<vector<char>>& board, string word,vector<vector<bool>> &visit,int index,int row,int col) {
        if (index == word.length()) return true;
        if (row < 0 || row >= board.size() || col < 0 || col >= board[0].size() 
                || visit[row][col] || word[index] != board[row][col]) {
            return false;
        }
        visit[row][col] = true;
        
        if(searchWord(board,word,visit,index + 1,row + 1,col)
            || searchWord(board,word,visit,index + 1,row - 1,col)
            || searchWord(board,word,visit,index + 1,row,col + 1)
            || searchWord(board,word,visit,index + 1,row,col - 1)) {
            return true;
        }
        visit[row][col] = false;
        return false;
    }


    bool exist(vector<vector<char>>& board, string word) {
        int rowSize = board.size();
        int colSize = board[0].size();
        vector<vector<bool>> mapping(rowSize, vector<bool>(colSize, false));
        for (int i=0; i<rowSize; i++) {
            for (int j=0; j<colSize; j++) {
                if (board[i][j] == word[0]) {
                    if (searchWord(board,word,mapping,0,i,j)) return true;
                }
            }
        }
        return false;
    }
};

BFS理论上可行,但是需要记录太多信息 - 每个点的坐标,当前word的index,和一个额外的(独立的)visit的map。特别是这个map,因为不能backtracking,所有每条path都需要自己独立的map

Remove Duplicates from Sorted List II
Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list.
For example,
Given 1->2->3->3->4->4->5, return 1->2->5.
Given 1->1->1->2->3, return 2->3.
----------------------------------------------------------------------
Solution #1, iterative

watch out for the tailing number(s)
1,2,2 // cut off
1,2,2,3 // re-attach
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *deleteDuplicates(ListNode *head) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if (head == NULL || head->next == NULL) return head;
        ListNode *ret = NULL, *itr = head->next,*cur = head;
        ListNode **pre = &ret;  // a pointer to a pointer
        while (itr != NULL) {
            if (cur->val != itr->val) {
                if (cur->next == itr) {
                    *pre = cur;
                    pre = &(cur->next);
                    cur = cur->next;
                }else {
                    cur = itr;
                }
            }
            itr = itr->next;
        }
        if (cur->next == NULL) {  // include it if the last one is singular
            *pre = cur;
        }else {  // otherwise, leave out the rest of the list 
            *pre = NULL;
        }
        return ret;
    }
};
Solution #2 from internet, recursive
ListNode *deleteDuplicates(ListNode *head) {
    // Start typing your C/C++ solution below
    // DO NOT write int main() function

    // base case, 0, or 1 item in the list
    if (head == NULL || head->next == NULL) return head;        
    ListNode *ret=NULL;
    ListNode *cur = head;
    int dup=0;

    // remove duplicated values from head
    while (cur->next != NULL && cur->val == cur->next->val)
    {
        ListNode *t=cur;
        cur=cur->next;
        delete(t);
        dup = 1;
    }

    if (!dup)
    {
        ret = cur;
        cur->next = deleteDuplicates(cur->next);            
    }
    else
    {
        ret = deleteDuplicates(cur->next);
    }    
    return ret;        
}


Update on Sep-18-2014
A simpler version of solution #1
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *deleteDuplicates(ListNode *head) {
        if (head == NULL || head->next == NULL) return head;
        ListNode *dummy = new ListNode(INT_MIN);
        dummy->next = head;
        ListNode *pre = dummy;
        
        while (head != NULL && head->next != NULL) {
            if (head->val != head->next->val) {
                pre = head;
                head = head->next;
            }else {
                while (head->next != NULL && head->val == head->next->val) {
                    head = head->next;
                }
                pre->next = head->next;
                head = head->next;
            }
            
        }
        
        return dummy->next;
    }
};

Friday, June 7, 2013

Day 34, 59, 61,63 Spiral Matrix II, Rotate List, Unique Paths II

Spiral Matrix II
Given an integer n, generate a square matrix filled with elements from 1 to n2 in spiral order.
For example,
Given n = 3,
You should return the following matrix:
[
 [ 1, 2, 3 ],
 [ 8, 9, 4 ],
 [ 7, 6, 5 ]
]
--------------------------------------
Solution #1 straightforward, follow spiral's track, O(n)
class Solution {
public:
    vector<vector<int> > generateMatrix(int n) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        vector<vector<int> > ret(n);
        if (n == 0) return ret;
        if (n == 1) {
            vector<int> v(1);
            v[0] = 1;
            ret[0] = v;
            return ret;
        }
        for (int i=0;i<n;i++) {
            vector<int> row(n);
            for (int j=0;j<n;j++) {
                row[j] = 0;
            }
            ret[i] = row;
        }
        int row=0,col=0,index=1;  
        while (ret[row][col] == 0) {
            // right
            while (col < n && ret[row][col] == 0) {
                ret[row][col] = index;
                index++;
                col++;
            }
            col--;
            row++;
            // down
            while (row < n && ret[row][col] == 0) {
                ret[row][col] = index;
                index++;
                row++;
            }
            row--;
            col--;
            // left
            while (col >= 0 && ret[row][col] == 0) {
                ret[row][col] = index;
                index++;
                col--;
            }
            col++;
            row--;
            // up
            while (row >= 0 && ret[row][col] == 0) {
                ret[row][col] = index;
                index++;
                row--;
            }
            row++;
            col++;
        }
        return ret;
    }
};
Update on Sep-13-2014
Solution #2
Go google it


Rotate List
Given a list, rotate the list to the right by k places, where k is non-negative.
For example:
Given 1->2->3->4->5->NULL and k = 2,
return 4->5->1->2->3->NULL.
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *rotateRight(ListNode *head, int k) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if (head == NULL || k == 0) return head;
        ListNode *cur=head, *end=head;
        int count=1;
        while (end->next != NULL) {
            count++;
            end = end->next;
        }
        k = k % count;
        if (k == 0) return head;
        for (int i=0;i<count-k-1;i++) {
            cur = cur->next;
        }
        ListNode *ret = cur->next;
        end->next = head;
        cur->next = NULL;
        return ret;
    }
};
Unique Paths II
Follow up for "Unique Paths":
Now consider if some obstacles are added to the grids. How many unique paths would there be?
An obstacle and empty space is marked as 1 and 0 respectively in the grid.
For example,
There is one obstacle in the middle of a 3x3 grid as illustrated below.
[
  [0,0,0],
  [0,1,0],
  [0,0,0]
]
The total number of unique paths is 2.
Note: m and n will be at most 100.
-----------------------------------
DP, based on unique path I
class Solution {
public:
    int uniquePathsWithObstacles(vector > &obstacleGrid) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        int matrix[101][101] = {0};
        int m = obstacleGrid.size() - 1;
        int n = obstacleGrid[0].size() - 1;
        matrix[m+1][n] = 1;
        for (int i=m;i>=0;i--) {
            for (int j=n;j>=0;j--) {
                if (obstacleGrid[i][j] == 0) {
                    matrix[i][j] = matrix[i+1][j] + matrix[i][j+1];
                }
            }
        }
        return matrix[0][0];
    }
};
Update on Sep-14-2014
Consider the case when matrix[m + 1][n] or matrix[m][n + 1] has an obstacle

O(n) space
class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        int m = obstacleGrid.size(), n = obstacleGrid[0].size();
        vector<int> dp(n + 1,0);
        if (obstacleGrid[m - 1][n - 1] == 1) return 0;
        dp[n - 1] = 1;
        
        for (int i = m - 1; i >= 0; i--) {
            for (int j = n - 1; j >= 0; j--) {
                if (obstacleGrid[i][j] == 1) {
                    dp[j] = 0;
                }else {
                    dp[j] += dp[j + 1];
                }
            }
        }
        return dp[0];
    }
};

Saturday, June 1, 2013

Day 32, 30,39,46, Substring with Concatenation of All Words, Combination Sum,Permutations

Substring with Concatenation of All Words
You are given a string, S, and a list of words, L, that are all of the same length. Find all starting indices of substring(s) in S that is a concatenation of each word in L exactly once and without any intervening characters.
For example, given:
S: "barfoothefoobarman"
L: ["foo", "bar"]
You should return the indices: [0,9].
(order does not matter).
------------------------------------------------------------------------
use two maps to count occurrences of all patterns, iterate through S to check if each word in L exactly occurs once in current part of S
solution is from internet
this is a boring and tasteless question
time and space complexity?
notice the conversion (int)S.size() in for loop
class Solution {  
public:  
    vector<int> findSubstring(string S, vector<string> &L) {  
        map<string, int> words;  
        map<string, int> curStr;  
        for(int i = 0; i < L.size(); ++i)  
            ++words[L.at(i)];  
        int N = L.size();  
        vector<int> ret;  
        if(N <= 0)   return ret;  
        int M = L.at(0).size();  
        for(int i = 0; i <= (int)S.size()-N*M; ++i)  
        {  
            curStr.clear();  
            int j = 0;  
            for(j = 0; j < N; ++j)  
            {  
                string w = S.substr(i+j*M, M);  
                if(words.find(w) == words.end())  
                    break;  
                ++curStr[w];  
                if(curStr[w] > words[w])  
                    break;  
            }  
            if(j == N)  ret.push_back(i);  
        }  
        return ret;  
    }  
};
Update on Sep-11-2014
The idea is similar to Longest Substring Without Repeating Characters. Each word has the same length and can be seen as a unique(or not) character.
A slightly different implementation is it can re-assign a new map at the beginning of outer loop.
Update on Feb-17-2015
COME_BACK
inner loop里的算法
#1 如果找不到当前word,重新设置map和start,重新开始
#2 如果找到且数量 > 0
#3 如果找到且数量 == 0: 从start开始pop旧的word,直到找到当前的为止

因为所有词为无序,不用保证维护当前的数组, 如
1 - 2 -..........3 - 2 - 1, 假设扫到3时已经找到所有的词
class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        unordered_map<string,int> dic;
        for (int i = 0; i < words.size(); i++) {
            if (dic.find(words[i]) == dic.end()) {
                dic[words[i]] = 1;
            }else {
                dic[words[i]]++;
            }
        }
        
        vector<int> rt;
        int wordLen = words[0].length();

        for (int i = 0; i < wordLen; i++) {
            int start = i,count = 0;
            unordered_map<string,int> temp = dic;
            for (int j = i; j < s.length(); j += wordLen) {
                string word = s.substr(j,wordLen);
                if (temp.find(word) == temp.end()) {
                    count = 0;
                    temp = dic;
                    start = j + wordLen;
                    continue;
                }else if (temp[word] > 0) {
                    temp[word]--;
                    count++;
                    if (count == words.size()) rt.push_back(start);
                }else if (temp[word] == 0) {
                    while (true) {
                        string begin = s.substr(start,wordLen);
                        if (begin == word) {
                            start += wordLen;
                            if (count == words.size()) rt.push_back(start);
                            break;
                        }
                        temp[begin]++;
                        count--;
                        start += wordLen;
                    }
                }
            }    
        }
        
        return rt;
    }
};

Java, updated on Sep-25th-2018
3种情况:
1. map有单词且次数大于0
2. map有单词但次数等于0
3. map不包含单词
2和3可以揉成一个branch

class Solution {
    public List<Integer> findSubstring(String s, String[] words) {
        
        Map<String, Integer> map = getMap(words);
        List<Integer> rt = new ArrayList<>();
        if (s.length() == 0 || words.length == 0) return rt;
        
        for (int i = 0; i < words[0].length(); i++) {
            rt.addAll(findSub(s, i, map, words[0].length(), words.length));    
        }
        
        return rt;
    }
    
    private List<Integer> findSub(String s, int i, Map<String, Integer> map, int len, int count) {
        List<Integer> rt = new ArrayList<>();
        Map<String, Integer> local = new HashMap<>(map);
        int start = i;
        int tempCount = count;
        
        while (i < s.length() - len + 1) {
            String word = s.substring(i, i + len);
            if (local.containsKey(word) && local.get(word) > 0) {
                local.put(word, local.get(word) - 1);
                i += len;
                tempCount--;
                
                if (tempCount == 0) {
                    rt.add(start);
                    String old = s.substring(start, start + len);
                    local.put(old, local.get(old) + 1);
                    start += len;
                    tempCount++;
                }
            }else {
                while (true) {
                    String old = s.substring(start, start + len);
                    if (old.equals(word)) {
                        start += len;
                        break;
                    }
                    local.put(old, local.get(old) + 1);
                    start += len;
                    tempCount++;
                }   
                i += len;
            }
        }
        
        return rt;
    }
    
    private Map<String, Integer> getMap(String[] words) {
        Map<String, Integer> map = new HashMap<>();
        for (String word : words) {
            map.put(word, map.getOrDefault(word, 0) + 1);
        }
        
        return map;
    }
}
}
Combination Sum
Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.
The same repeated number may be chosen from C unlimited number of times.
Note:
  • All numbers (including target) will be positive integers.
  • Elements in a combination (a1, a2, � , ak) must be in non-descending order. (ie, a1 ? a2 ? � ? ak).
  • The solution set must not contain duplicate combinations.
For example, given candidate set 2,3,6,7 and target 7,
A solution set is:
[7]
[2, 2, 3]
-------------------------------------------------------------
combination

class Solution {
public:
    void comb (vector<int> &candidates, int target,vector<vector<int> > &ret,vector<int> cur,int start) {
        if (target == 0) {
            ret.push_back(cur);
        }else {
            for (int i=start;i<candidates.size();i++) {
                if (target - candidates[i] >= 0) {
                    vector<int> v = cur;  // Attention here!!!
                    v.push_back(candidates[i]);
                    comb(candidates,target-candidates[i],ret,v,i);
                }
            }
        }
    }

    vector<vector<int> > combinationSum(vector<int> &candidates, int target) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        sort(candidates.begin(),candidates.end());
        vector<vector<int> > ret;
        vector<int> cur;
        comb(candidates,target,ret,cur,0);
        return ret;
    }
};
class Solution {
public:
    void comb(vector<vector<int> > &rt, vector<int> &candidates, vector<int> cur, int target, int index) {
        if (target == 0) {
            rt.push_back(cur);
            return;
        } 
        if (index >= candidates.size() || target < 0) return;
        
        comb(rt,candidates,cur,target,index + 1);
        cur.push_back(candidates[index]);
        comb(rt,candidates,cur,target - candidates[index],index);
    } 

    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        sort(candidates.begin(),candidates.end());
        vector<vector<int> > rt;
        vector<int> cur;
        comb(rt,candidates,cur,target,0);
        
        return rt;
    }
};
Permutations
Given a collection of numbers, return all possible permutations.
For example,
[1,2,3] have the following permutations:
[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], and [3,2,1].
--------------------------------------------------------------------
class Solution {
public:
    void per (vector<int> num,vector<int> cur,vector<vector<int> > &ret) {
        if (num.size() == 0) {
            ret.push_back(cur);
        }
        for (int i=0;i<num.size();i++) {
            vector<int> v = cur;
            vector<int> w = num;
            v.push_back(w[i]);
            w.erase(w.begin()+i);
            per(w,v,ret);
        }
    }

    vector<vector<int> > permute(vector<int> &num) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        vector<vector<int> > ret;
        vector<int> cur;
        per(num,cur,ret);
        return ret;
    }
};

#1 以index为分界线,来区分已经使用和未使用的集合(此条不一定为正确,需看代码)
#2 换句话说,每一个recursive call,都遍历所有未使用的数字确定在index(n次)
index = 0: 123, 213, 321
index = 1: 132, 231, 312
index = 2: 插入
class Solution {
public:
    void swap(vector<int> &nums,int i,int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }

    void per(vector<vector<int> > &rt, vector<int> &nums, int index) {
        if (nums.size() == index) {
            rt.push_back(nums);
            return;
        }
        
        for (int i = index; i < nums.size(); i++) {
            swap(nums,i,index);
            per(rt,nums,index + 1);
            swap(nums,i,index); // 此行可以不加,结果同样正确,因为每一次都会确定一个数
        }
    }

    vector<vector<int>> permute(vector<int>& nums) {
        vector<vector<int> > rt;
        per(rt,nums,0);
        
        return rt;
    }
};

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

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

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