Wednesday, January 22, 2014

## other: Longest common subsequence

http://lintcode.com/en/problem/longest-common-subsequence/
Let the input sequences be X[0..m-1] and Y[0..n-1] of lengths m and n respectively. And let L(X[0..m-1], Y[0..n-1]) be the length of LCS of the two sequences X and Y. Following is the recursive definition of L(X[0..m-1], Y[0..n-1]).

If last characters of both sequences match (or X[m-1] == Y[n-1]) then
L(X[0..m-1], Y[0..n-1]) = 1 + L(X[0..m-2], Y[0..n-2])

If last characters of both sequences do not match (or X[m-1] != Y[n-1]) then
L(X[0..m-1], Y[0..n-1]) = MAX ( L(X[0..m-2], Y[0..n-1]), L(X[0..m-1], Y[0..n-2])

--------------------------
print the length of the longest common sub-sequence
DP
The actual sequence can be generated by using backtrack.
Reference:
http://en.wikipedia.org/wiki/Longest_common_subsequence_problem
int lcs (string a, string b) {
    int m = a.length();
    int n = b.length();
    vector<vector<int> > dp(m + 1, vector<int>(n + 1, 0));
    
    for (int i = 1; i < m + 1; i++) {
        for (int j = 1; j < n + 1; j++) {
            if (a[i] == b[i]) {
                dp[i][j] = 1 + dp[i - 1][j - 1];
            }else {
                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
            }
        }
    }
    return dp[m][n];
} 
-------------------------------------------------
Recursion

int lcs( char *X, char *Y, int m, int n )
{
   if (m == 0 || n == 0)
     return 0;
   if (X[m-1] == Y[n-1])
     return 1 + lcs(X, Y, m-1, n-1);
   else
     return max(lcs(X, Y, m, n-1), lcs(X, Y, m-1, n));
}

Friday, January 17, 2014

## Other: Check if a given Binary Tree is SumTree, Stack implementation

Check for SumTree
bool isLeaf (Node* root) {
    if (root->left == NULL && root->right == NULL) {
        return true;
    }
    else return false;
}


bool isSumTree (Node* root) {
    if (root == NULL || isLeaf(root)) {
        return true;
    }
    
    if (isSumTree(root->left) && isSumTree(root->right)) {
        int leftSum = 0, rightSum = 0;
        
        if (isLeaf(root->left)) {
            leftSum = left->val;
        }else if (root->left == NULL) {
            leftSum = 0;
        }else {
            leftSum = root->left->val * 2;
        }
        
        if (isLeaf(root->right)) {
            rightSum = right->val;
        }else if (root->right == NULL) {
            rightSum = 0;
        }else {
            rightSum = root->right->val * 2;
        }
        
        return root->val == (rightSum + leftSum);
    }
    
    return false;
}

The algorithm would be the same if we want to turn a tree to a valid sum tree ------------------------------------------------ Q: Implement a Stack class with O(1) min function. A: use an extra stack to contain all min values, O(n) space, use (push 2 * value - min to stack) to optimize space to O(1)

Saturday, January 11, 2014

Notes on Notes -- Chapter 1

string search algorithm
rabin-karp, rolling hash
kmp

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

e.g. 1 Given input "Mr John Smith", output "Mr%20John%20Smith" (CtCI 1.4)
e.g. 2 Given input "Mr%20John%20Smith" , output "Mr John Smith" (Facebook interview)
e.g. 3 Given two sorted arrays, merge B into A in sorted order. (CtCI 11.1, Leetcode: Merge Sorted Array)

扫描2次 + 倒叙赋值

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

what is / how to use stringstream in c++

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

If mat[i][j] is 0, then set the entire row and column to 0

use first row and first column to store the matrix's rows' and columns' turns

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

Implement a method rand7() given rand5().(CtCI:17.11)

  
unsigned long hashstring(unsigned char *str)
{
    unsigned long hash = 5381;
    int c;

    while (c = *str++)
        hash = ((hash << 5) + hash) + c; /* hash * 33 + c */

    return hash;
}
-------------------------------------------------
 A hash function for the state of a chess game.(EPI: 12.2) 
 
fun to read:  
http://stackoverflow.com/questions/1831386/programmer-puzzle-encoding-a-chess-board-state-throughout-a-game 

Saturday, January 4, 2014

Day 74, ##, Sort List, Evaluate Reverse Polish Notation

Sort List
Sort a linked list in O(n log n) time using constant space complexity.
-----------------------------------------------------------------
Solution #1, recursive merge sort
wiki page has iterative buttom-up method
http://en.wikipedia.org/wiki/Merge_sort
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* merge (ListNode *&left, ListNode *&right) {
        ListNode* dummy = new ListNode(INT_MIN); // dummy
        ListNode* itr = dummy;
        while (left != NULL && right != NULL) {
            if (left->val <= right->val) {
                itr->next = left;
                itr = left;
                left = left->next;
            }else {
                itr->next = right;
                itr = right;
                right = right->next;
            }
        }
        if (right == NULL) itr->next = left;
        if (left == NULL) itr->next = right;
        return dummy->next;
    }

    ListNode *sortList(ListNode *head) {
        // divide
        if (head == NULL || head->next == NULL) {
            return head;
        }
        
        ListNode *slow = head, *fast = head->next;
        while (fast != NULL) {
            fast = fast->next;
            if (fast != NULL) {
                fast = fast->next;
                slow = slow->next;
            }
        }
        ListNode *second = slow->next;
        slow->next = NULL;
        
        head = sortList(head);
        second = sortList(second);
        
        // merge
        return merge(head,second);
    }
};
Update Jan-5-2015
dummy should be deleted in merge

Evaluate Reverse Polish Notation
Evaluate the value of an arithmetic expression in Reverse Polish Notation.
Valid operators are +, -, *, /. Each operand may be an integer or another expression.
Some examples:

  ["2", "1", "+", "3", "*"] -> ((2 + 1) * 3) -> 9
  ["4", "13", "5", "/", "+"] -> (4 + (13 / 5)) -> 6
----------------------------------------------------
post order, using stack
注意从stack出来时的顺序,RPN是最先进stack的在前面。
class Solution {
public:
    int arith (int op1, int op2, string opt) {
        if (opt == "+") {
            return op1 + op2;
        }else if (opt == "-") {
            return op1 - op2;
        }else if (opt == "*") {
            return op1 * op2;
        }else if (opt == "/") {
            return op1 / op2;
        }
    }

    int evalRPN(vector<string> &tokens) {
        stack<int> s;
        int num = 0;
        for (int i = 0; i < tokens.size(); i++) {
            if (isdigit(tokens[i][0]) || (tokens[i].length() > 1 && isdigit(tokens[i][1]))) {
                num = atoi(tokens[i].c_str());
            }else {
                int operand1 = s.top();
                s.pop();
                int operand2 = s.top();
                s.pop();
                num = arith(operand2,operand1,tokens[i]);
            }
            s.push(num);
        }
        return num;
    }
};

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