Showing posts with label recursion. Show all posts
Showing posts with label recursion. Show all posts

Friday, July 3, 2015

Day 115, #229, Majority Element II, Kth Smallest Element in a BST

Majority Element II
Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times. The algorithm should run in linear time and in O(1) space.
Hint:
  1. How many majority elements could it possibly have?
---------------------------------------
注意for loop里的判断
class Solution {
public:
    vector<int> majorityElement(vector<int>& nums) {
        vector<int> rt;
        if (nums.size() == 0) return rt;
        
        int num1 = 0, num2 = 0, count1 = 0, count2 = 0;
        for (int i = 0; i < nums.size(); i++) {
            if (count1 == 0 && (count2 == 0 || nums[i] != num2)) {
                num1 = nums[i];
                count1++;
            }else if (count2 == 0 && nums[i] != num1){
             count2++;
             num2 = nums[i];
            }else if (nums[i] == num1) {
                count1++;
            }else if (nums[i] == num2) {
                count2++;
            }else {
                count1--;
                count2--;
            }
        }
        
        count1 = 0;
        count2 = 0;
        for (int i = 0; i < nums.size(); i++) {
            if (nums[i] == num1) count1++;
            else if (nums[i] == num2) count2++;
        }
        if (count1 * 3 > nums.size()) rt.push_back(num1);
        if (count2 * 3 > nums.size()) rt.push_back(num2);
        return rt;
    }
};

Kth Smallest Element in a BST
Given a binary search tree, write a function kthSmallest to find the kth smallest element in it.
Note: 
You may assume k is always valid, 1 ≤ k ≤ BST's total elements.
Follow up:
What if the BST is modified (insert/delete operations) often and you need to find the kth smallest frequently? How would you optimize the kthSmallest routine?
-------------------------------------------------------------------------------
COME BACK for the follow up
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    void preorder(TreeNode* root, int &k, TreeNode *&kth) {
        if (root == NULL) return;
        preorder(root->left,k,kth);
        k--;
        if (k == 0) kth = root;
        else preorder(root->right,k,kth);
    }

    int kthSmallest(TreeNode* root, int k) {
        TreeNode *kth = NULL;
        preorder(root,k,kth);
        return kth->val;
    }
};

另一种做法,找出子树的数量 updated on Jan-4th-2019
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    private TreeNode rt = null;
    public int kthSmallest(TreeNode root, int k) {
        dfs(root, k);
        return rt.val;
    }
    
    private int dfs(TreeNode root, int k) {
        if (root == null) return 0;
        int l = dfs(root.left, k);
        
        if (l + 1 == k) {
            rt = root;
        }
        
        int r = dfs(root.right, k - l - 1);
        return l + r + 1;
    }
}

Follow up
修改TreeNode结构,加入count。O(n)重建树,O(lg n) 找到Kth smallest

Wednesday, June 24, 2015

Day 112, ##, Count Complete Tree Nodes, Rectangle Area, Basic Calculator, Implement Stack using Queues, Invert Binary Tree

Count Complete Tree Nodes
Given a complete binary tree, count the number of nodes.
Definition of a complete binary tree from Wikipedia:
In a complete binary tree every level, except possibly the last, is completely filled, and all nodes in the last level are as far left as possible. It can have between 1 and 2hnodes inclusive at the last level h.
--------------------------------------------
O(logN * logN),遇到perfect tree, 直接计算并返回,反之继续数儿子们
看了答案
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int countNodes(TreeNode* root) {
       if (root == NULL) return 0;
       int left = 0, right = 0;
       TreeNode *leftItr = root, *rightItr = root;
       while (leftItr != NULL) {
           left++;
           leftItr = leftItr->left;
       }
       
       while (rightItr != NULL) {
           right++;
           rightItr = rightItr->right;
       }
       
       if (left == right) return pow(2,left) - 1;
       return 1 + countNodes(root->left) + countNodes(root->right);
    }
};

iterative
检查右子树是不是perfect tree,如果是,则缺口在左子树,此时加上右边的个数。
如果不是,则缺口在右子树,此时加上左边的个数
此题关键在于对高度的判断,然后对树的分解
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int getHeight(TreeNode *root) {
        int height = 0;
        while (root != NULL) {
            height++;
            root = root->left;
        }
        
        return height;
    }

    int countNodes(TreeNode* root) {
        int height = getHeight(root);
        int count = 0;
        while (root != NULL) {
            if (getHeight(root->right) == height - 1) {
                count += 1 << height - 1;
                root = root->right;
            }else {
                count += 1 << height - 2;
                root = root->left;
            }
            
            height--;
        }
        
        return count;
    }
};

Rectangle Area
Find the total area covered by two rectilinear rectangles in a 2D plane.
Each rectangle is defined by its bottom left corner and top right corner as shown in the figure.
Rectangle Area
Assume that the total area is never beyond the maximum possible value of int.
----------------------------------------------
看了答案
class Solution {
public:
    int computeArea(int A, int B, int C, int D, int E, int F, int G, int H) {
        if (D < F || H < B || G < A || C < E) {
            return (H - F) * (G - E) + (C - A) * (D - B);
        }
        
        int right = min(D,H) - max(B,F);
        int top = min(C,G) - max(E,A);
        
        return (D - B) * (C - A) + (H - F) * (G - E) - right * top;
    }
};

Basic Calculator
Implement a basic calculator to evaluate a simple expression string.
The expression string may contain open ( and closing parentheses ), the plus + or minus sign -non-negative integers and empty spaces .
You may assume that the given expression is always valid.
Some examples:
"1 + 1" = 2
" 2-1 + 2 " = 3
"(1+(4+5+2)-3)+(6+8)" = 23
---------------------------------------------------------------------
看了答案,用初始化 sign = 1来处理符号,能解决特殊情况.
对()的处理
class Solution {
public:
    int calculate(string s) {
        stack<int> st;
        int sign = 1;
        int rt = 0;
        int num = 0;
        
        for (int i = 0; i < s.length(); i++) {
            if (isdigit(s[i])) {
                num = num * 10 + s[i] - '0';
            }else if (s[i] == '+') {
                rt += sign * num;
                sign = 1;
                num = 0;
            }else if (s[i] == '-') {
                rt += sign * num;
                sign = -1;
                num = 0;
            }else if (s[i] == '(') {
                st.push(rt);
                st.push(sign);
                sign = 1;
                rt = 0;
            }else if (s[i] == ')') {
                rt += num * sign;
                sign = st.top();
                st.pop();
                rt = sign * rt + st.top();
                st.pop();
                num = 0;
            }
        }
        
        if (num != 0) {
            return rt + sign * num;
        }
        
        return rt;
    }
};
Java, updated on Aug-16th-2018. 整体思路类似,只不过遇到数字做加减。上面c++的算法是遇到符号做加减。
class Solution {
    public int calculate(String s) {
        Stack<Integer> st = new Stack<>();
        int i = 0;
        int eval = 0;
        int sign = 1;
        
        while (i < s.length()) {
            char c = s.charAt(i);
            if (c == '(') {
                st.push(eval);
                st.push(sign);
                eval = 0;
                sign = 1;
            }else if (c == ')') {
                sign = st.pop();
                eval = st.pop() + eval * sign;
            }else if (Character.isDigit(c)) {
                String cur = "";
                while (i < s.length() && Character.isDigit(s.charAt(i))) {
                    cur += s.charAt(i);
                    i++;
                }
                i--;
                eval += sign * Integer.parseInt(cur);
            }else if (c == '-') {
                sign = -1;
            }else if (c == '+') {
                sign = 1;
            }
            
            i++;
        }
        
        return eval;
    }
}

Implement Stack using Queues
Implement the following operations of a stack using queues.
  • push(x) -- Push element x onto stack.
  • pop() -- Removes the element on top of the stack.
  • top() -- Get the top element.
  • empty() -- Return whether the stack is empty.
Notes:
  • You must use only standard operations of a queue -- which means only push to backpeek/pop from frontsize, and is empty operations are valid.
  • Depending on your language, queue may not be supported natively. You may simulate a queue by using a list or deque (double-ended queue), as long as you use only standard operations of a queue.
  • You may assume that all operations are valid (for example, no pop or top operations will be called on an empty stack).
----------------------------------------------------
用queue的大小来控制倒腾,只用一个queue,而不是两个
class Stack {
public:
    // Push element x onto stack.
    void push(int x) {
        topElem = x;
        q.push(x);
    }

    // Removes the element on top of the stack.
    void pop() {
        for (int i = 0; i < q.size() - 1; i++) {
            topElem = q.front();
            q.push(q.front());
            q.pop();
        }
        q.pop();
    }
    
    // Get the top element.
    int top() {
        return topElem;
    }

    // Return whether the stack is empty.
    bool empty() {
        return q.empty();
    }
private:
    queue<int> q;
    int topElem;
};

Invert Binary Tree
Invert a binary tree.
     4
   /   \
  2     7
 / \   / \
1   3 6   9
to
     4
   /   \
  7     2
 / \   / \
9   6 3   1
---------------------------------------------------
recursive
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if (root == NULL) return NULL;
        TreeNode *temp = root->left;
        root->left = invertTree(root->right);
        root->right = invertTree(temp);
        
        return root;
    }
};

iterative
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if (root == NULL) return root;
        queue<TreeNode *> que;
        que.push(root);
        
        while (!que.empty()) {
            TreeNode *node = que.front();
            que.pop();
            TreeNode *temp = node->left;
            node->left = node->right;
            node->right = temp;
            
            if (node->left != NULL) {
                que.push(node->left);
            }
            if (node->right != NULL) {
                que.push(node->right);
            }
        }
        
        return root;
    }
};

Sunday, December 21, 2014

Day 85, #97, Interleaving String


Interleaving String


Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2.
For example,
Given:
s1 = "aabcc",
s2 = "dbbca",
When s3 = "aadbbcbcac", return true.
When s3 = "aadbbbaccc", return false.
------------------------------------------------------
Solution #1, straight forward recursion 
class Solution {
public:
    bool isInter(string s1, int i1, string s2, int i2, string s3, int i3) {
        if (i3 == s3.length()) {
            return true;
        }
        
        if (i1 < s1.length() && s1[i1] == s3[i3] && isInter(s1,i1 + 1,s2,i2,s3,i3 + 1)) {
            return true;
        }
        
        if (i2 < s2.length() && s2[i2] == s3[i3] && isInter(s1,i1,s2,i2 + 1,s3,i3 + 1)) {
            return true;
        }
        
        return false;
        
    }

    bool isInterleave(string s1, string s2, string s3) {
        return isInter(s1,0,s2,0,s3,0);
    }
};
Solution #2 DP, similar logi. dp[i][j] means if s1[0 : i] and s2[0 : j] can match s3[0 : i + j + 1]
不用检查s3[0]是因为,只有在s1或s2长度为0时,s3[0]才有被检查的必要,这我们已经在initialization的时候已经做过 
***一定要想清楚 dp[i][j] 所代表的意思***
class Solution {
public:
    bool isInterleave(string s1, string s2, string s3) {
        int len1 = s1.length();
        int len2 = s2.length();
        if (len1 + len2 != s3.length()) return false;
        
        // check empty strings
        if (len1 == 0) {
            if (s2 == s3) {
                return true;
            }else {
                return false;
            }
        }
        if (len2 == 0) {
            if (s1 == s3) {
                return true;
            }else {
                return false;
            }
        }
        
        vector<vector<bool> > dp(len1 + 1,vector<bool>(len2 + 1,false));
        
        // initialize dp
        dp[0][0] = true;
        for (int i = 1; i <= len1; i++) {
            if (s1[i - 1] == s3[i - 1]) {
                dp[i][0] = true;
            }else {
                break;
            }
        }
        
        for (int i = 1; i <= len2; i++) {
            if (s2[i - 1] == s3[i - 1]) {
                dp[0][i] = true;
            }else {
                break;
            }
        }
        
        for (int i = 0; i < len1; i++) {
            for (int j = 0; j < len2; j++) {
                if (s1[i] == s3[i + j + 1] && dp[i][j + 1]) {
                    dp[i + 1][j + 1] = true;
                }
                
                if (s2[j] == s3[i + j + 1] && dp[i + 1][j]) {
                    dp[i + 1][j + 1] = true;
                }
            }
        }
        
        return dp[len1][len2];
    }
};

可以简化为O(n) space, 就不写了

Saturday, December 20, 2014

Day 84, #87, Scramble String


Scramble String

Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrings recursively.
Below is one possible representation of s1 = "great":
    great
   /    \
  gr    eat
 / \    /  \
g   r  e   at
           / \
          a   t
To scramble the string, we may choose any non-leaf node and swap its two children.
For example, if we choose the node "gr" and swap its two children, it produces a scrambled string "rgeat".
    rgeat
   /    \
  rg    eat
 / \    /  \
r   g  e   at
           / \
          a   t
We say that "rgeat" is a scrambled string of "great".
Similarly, if we continue to swap the children of nodes "eat" and "at", it produces a scrambled string "rgtae".
    rgtae
   /    \
  rg    tae
 / \    /  \
r   g  ta  e
       / \
      t   a
We say that "rgtae" is a scrambled string of "great".
Given two strings s1 and s2 of the same length, determine if s2 is a scrambled string of s1.
-------------------------------------------------------------
Solution #1 recursive
bool scramble(string s1,string s2) {
    if (s1 == s2) return true;    
    string t1 = s1,t2 = s2;
    sort(t1.begin(),t1.end());
    sort(t2.begin(),t2.end());
    if (t1 != t2) return false;
    
    for (int i = 1; i < s1.length(); i++) {
        string p1 = s1.substr(0,i), p2 = s1.substr(i);
        string q1 = s2.substr(0,i), q2 = s2.substr(i); 
        string q3 = s2.substr(s2.length() - i), q4 = s2.substr(0,s2.length() - i);
        
        if ((scramble(p1,q1) && scramble(p2,q2)) || (scramble(p1,q3) && scramble(p2,q4))) return true;
    }
    return false;
}

Solution #2 recursive + memo
找出s1所有的scrambled strings,然后一一对比
class Solution {
public:
    unordered_map<string,vector<string>> dic;
    void combine(vector<string> &rt,vector<string> &v1,vector<string> &v2) {
        for (string s1 : v1) {
            for (string s2 : v2) {
                rt.push_back(s1 + s2);
                rt.push_back(s2 + s1);
            }
        }
    }

    vector<string> permutation(string s) {
        vector<string> rt;
        if (s.length() == 1) {
            rt.push_back(s);
        }
    
        for (int i = 1; i < s.length(); i++) {
            string s0 = s.substr(0,i);
            string s1 = s.substr(i);
            vector<string> v1,v2; 
            if (dic.find(s0) != dic.end()) {
                v1 = dic[s0];
            }else {
                v1 = permutation(s0);
                dic[s0] = v1;   
            }
            
            if (dic.find(s1) != dic.end()) {
                v2 = dic[s1];
            }else {
                v2 = permutation(s1);
                dic[s1] = v2;
            }
            combine(rt,v1,v2);
        }
        
        return rt;
    }

    bool isScramble(string s1, string s2) {
        vector<string> rt = permutation(s1);
        for (string s : rt) {
            if (s == s2) return true;
        }
        
        return false;
    }
};

Solution #3 3-dimensional DP
dp[length][index at s1][index at s2]
int the most inner loop, delimiter breaks string in k - 1 different ways. same logic as recursive
注意loop里的终止条件
class Solution {
public:
    bool isScramble(string s1, string s2) {
        int len = s1.length();
        
        vector<vector<vector<bool> > > dp(len,vector<vector<bool> >(len,vector<bool>(len,false)));
        
        for (int i = 0; i < len; i++) {
            for (int j = 0; j < len; j++) {
                if (s1[i] == s2[j]) {
                    dp[0][i][j] = true;
                } 
            }
        }
        
        for (int k = 2; k <= len; k++) {
            for (int i = 0; i <= len - k; i++) {
                
                for (int j = 0; j <= len - k; j++) {

                    for (int delimiter = 1; delimiter < k; delimiter++) {
                        
                        if (dp[delimiter - 1][i][j] && dp[k - delimiter - 1][i + delimiter][j + delimiter]) {
                            dp[k - 1][i][j] = true;
                            break;
                        }
                            
                        if (dp[delimiter - 1][i][j + k - delimiter] && dp[k - delimiter - 1][i + delimiter][j]) {
                            dp[k - 1][i][j] = true;
                            break;
                        }
                        
                    }
                }
                
            }
            
        }
    
        return dp[len - 1][0][0];
    }
};

Saturday, December 13, 2014

Day 79, #44, Wildcard Matching


Wildcard Matching


Implement wildcard pattern matching with support for '?' and '*'.
'?' Matches any single character.
'*' Matches any sequence of characters (including the empty sequence).

The matching should cover the entire input string (not partial).

The function prototype should be:
bool isMatch(const char *s, const char *p)

Some examples:
isMatch("aa","a") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "*") → true
isMatch("aa", "a*") → true
isMatch("ab", "?*") → true
isMatch("aab", "c*a*b") → false
---------------------------------------------------------------
Solution #1 recursion, OJ time limit exceeded
class Solution {
public:
    bool isMatch(const char *s, const char *p) {
        if (*p == '\0') {
            return *s == '\0';
        }
        
        if (*p == *s || *p == '?') {
            return isMatch(s + 1, p + 1);
        }
        
        if (*p == '*') {
            while (*s != '\0') {
                if(isMatch(s,p + 1)) {
                    return true;
                }
                s++;
            }
        }
        
        return false;
    }
};

Solution #2, dp with 2d arrays,
class Solution {
public:
    bool isMatch(string s, string p) {
        int m = p.length(), n = s.length();
        vector<vector<bool> > dp(m + 1,vector<bool>(n + 1,false));
        
        dp[0][0] = true;
        for (int i = 0; i < m; i++) {
         if (p[i] != '*') break;
            dp[i + 1][0] = true;
        }
        
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (dp[i][j] && (p[i] == s[j] || p[i] == '?')) {
                    dp[i + 1][j + 1] = true;
                }else if (p[i] == '*') {
                    if (dp[i][j + 1] || dp[i + 1][j]) {
                        dp[i + 1][j + 1] = true;
                    }
                }
            }
        }
        return dp[m][n];
    }
};

改良版DP,用了一个一维数组,当*p == '*',dp[j]只取决于dp[j - 1],过不了最后一个test case
class Solution {
public:
    bool isMatch(string s, string p) {
        int m = p.length(), n = s.length();
        vector<bool> dp(n + 1,false);
        bool diag = true;
        dp[0] = true;
        
        for (int i = 0; i < m; i++) {
            diag = dp[0];
            for (int j = 0; j < n; j++) {
                if (diag && (p[i] == s[j] || p[i] == '?')) {
                    diag = dp[j + 1];
                    dp[j + 1] = true;
                }else if (p[i] == '*') {
                    diag = dp[j + 1];
                    if (dp[j] || dp[j + 1]) {
                        dp[j + 1] = true;
                    }
                }else {
                    diag = dp[j + 1];
                    dp[j + 1] = false;
                }
            }
            if (p[i] == '*' && dp[0]) {
                dp[0] = true;
            }else {
                dp[0] = false;
            }
            
        }
        
        return dp[n];
    }
};

Solution #3, constant space
star用来记录最近*的位置,index用来记录当前*匹配成功后s的位置。*之前全部匹配成功,不用再重复检测。*之后如果匹配失败,回头从star + 1 和 index重新匹配,每匹配失败一次,index增加一位。
class Solution {
public:
    bool isMatch(const char *s, const char *p) {
        const char *star = NULL;
        const char *index = s;
        
        while (*s != '\0') {
            if (*s == *p || *p == '?') {
                s++;
                p++;
            }else if (*p == '*') {
                star = p;
                p++;
                index = s;
            }else if (star != NULL) {
                p = star + 1;
                index++;
                s = index;
            }else return false;
        }
        
        while (*p == '*') {
            p++;
        }
        
        return *p == '\0';
    }
};
Java,2维dp
class Solution {
    public boolean isMatch(String s, String p) {
        List<List<Boolean>> dp = getDP(s, p);
            
        for (int i = 0; i < p.length(); i++) {
            for (int j = 0; j < s.length(); j++) {
                if (dp.get(i).get(j) && (s.charAt(j) == p.charAt(i) || p.charAt(i) == '?')) {
                    dp.get(i + 1).set(j + 1, true);
                } else if (p.charAt(i) == '*' && (dp.get(i).get(j + 1) || dp.get(i + 1).get(j))) {
                    dp.get(i + 1).set(j + 1, true);
                }
            }
        }
        
        return dp.get(p.length()).get(s.length());
    }
    
    private List<List<Boolean>> getDP(String s, String p) {
        int m = s.length();
        int n = p.length();
        List<List<Boolean>> dp = new ArrayList<>();
        for (int i = 0; i < n + 1; i++) {
            List<Boolean> inner = new ArrayList<>();
            if (i == 0 || (i > 0 && dp.get(i - 1).get(0) && p.charAt(i - 1) == '*')) inner.add(true);
            else inner.add(false);
            for (int j = 0; j < m; j++) {
                inner.add(false);
            }
            dp.add(inner);
        }
        
        return dp;

    }
}

Sunday, November 30, 2014

Day 76, #10, Regular Expression Matching

Regular Expression Matching
Implement regular expression matching with support for '.' and '*'.
'.' Matches any single character.
'*' Matches zero or more of the preceding element.

The matching should cover the entire input string (not partial).

The function prototype should be:
bool isMatch(const char *s, const char *p)

Some examples:
isMatch("aa","a") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "a*") → true
isMatch("aa", ".*") → true
isMatch("ab", ".*") → true
isMatch("aab", "c*a*b") → true
 ------------------------------------------------------------------------------
Solution #1, recursion
class Solution {
public:
    bool isMatch(const char *s, const char *p) {
        if (*p == '\0') {
            return *s == '\0';
        }
        
        if (*(p + 1) != '*') {
            return (*s == *p || (*p == '.' && *s != '\0')) && isMatch(s + 1, p + 1);
        }

        while (*p == *s || (*p == '.' && *s != '\0')) {
            if (isMatch(s,p + 2)) {
                return true;
            }
            s++;
        }
        return isMatch(s,p + 2);
    }
};

Solution #2, DP
dp[i][j] has the boolean value whether p[0 : i] can match s[0 : j], dp[0][0] is set to true since empty string matches empty pattern
class Solution {
public:
    bool isMatch(const char *s, const char *p) {
        int m = strlen(p);
        int n = strlen(s);
        
        vector<vector<bool> > dp(m + 1,vector<bool>(n + 1,false));
        dp[0][0] = true;
        
        for (int i = 2; i <= m; i++) {
            if (p[i - 1] == '*' && dp[i - 2][0]) {
                dp[i][0] = true;
            }
        }
        
        for (int i = 1; i <= m; i++) {
            
            for (int j = 1; j <= n; j++) {
                if (p[i - 1] == s[j - 1] || p[i - 1] == '.') {
                    dp[i][j] = dp[i - 1][j - 1];
                }else if (p[i - 1] == '*') {
                    // 1 or more char
                    if (dp[i][j - 1] && (p[i - 2] == s[j - 1] || p[i - 2] == '.')) {
                        dp[i][j] = true;
                    }
                    // zero char
                    else if (i - 2 >= 0 && dp[i - 2][j]) {
                        dp[i][j] = true;
                    }
                }
            }
            
        }
        
        return dp[m][n];
    }
};

class Solution {
public:
    bool helper(string s,string p,int i,int j) {
        if (j == p.length()) return i == s.length();
        
        if (j == p.length() - 1 || (j + 1 < p.length() && p[j + 1] != '*')) {
            if (i < s.length() && (p[j] == s[i] || p[j] == '.')) {
                return helper(s,p,i + 1,j + 1);
            }
            return false;
        }
        
        while (i < s.length() && (p[j] == s[i] || p[j] == '.')) {
            if (helper(s,p,i,j + 2)) {
                return true;
            }
            i++;
        }
        return helper(s,p,i,j + 2);
    }
    
    bool isMatch(string s, string p) {
        return helper(s,p,0,0);
    }
};

Java
关键:把下一个 == '*' 和 != '*' 两种情况分开处理

class Solution {
    public boolean isMatch(String s, String p) {
        return rec(s,p,0,0);
    }
    
    private boolean rec(String s, String p, int i, int j) {
        if (i == s.length() && j == p.length()) {
            return true;
        }
        
        if (j + 1 < p.length() && p.charAt(j + 1) == '*') {
            int temp = i;
            while (temp < s.length() && (s.charAt(temp) == p.charAt(j) || p.charAt(j) == '.')) {
                if (rec(s, p, temp + 1, j + 2)) return true;
                temp++;
            }
            return rec(s,p,i,j + 2); // '*' matches zero chars
        }
        
        if (i < s.length() && j < p.length() && (s.charAt(i) == p.charAt(j) || p.charAt(j) == '.')) {
            return rec(s, p, i + 1, j + 1);
        }
    
        return false;
    }
}
预处理的时候要回头看2位之前的位置。
主函数中还要考虑'*' match 0个的情况
class Solution {
    public boolean isMatch(String s, String p) {
        List<List<Boolean>> dp = getDP(s, p);
        int m = p.length();
        int n = s.length();
        
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <=n; j++) {
                if (p.charAt(i - 1) == s.charAt(j - 1) || p.charAt(i - 1) == '.') {
                    dp.get(i).add(j, dp.get(i - 1).get(j - 1));
                } else if (p.charAt(i - 1) == '*') {
                    if (i - 2 >= 0 && dp.get(i - 2).get(j)) {
                        dp.get(i).add(j, true);
                    }else if (dp.get(i).get(j - 1) && (p.charAt(i - 2) == s.charAt(j - 1) || p.charAt(i - 2) == '.')) {
                        dp.get(i).add(j, true);
                    }
                }
            }
        }
        
        return dp.get(m).get(n);
    }
    
    private List<List<Boolean>> getDP(String s, String p) {
        int m = p.length();
        int n = s.length();
        List<List<Boolean>> dp = new ArrayList<>();
        
        for (int i = 0; i <= m; i++) {
            List<Boolean> list = new ArrayList<>();
            if (i == 0 || (p.charAt(i - 1) == '*' && dp.get(i - 2).get(0))) list.add(true);
            else list.add(false);
            for (int j = 0; j < n; j++) {
                list.add(false);
            }
            dp.add(list);
        }
        
        return dp;
    }
}

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, December 27, 2013

Day 67, #117, #123, #124, Populating Next Right Pointers in Each Node II, Best Time to Buy and Sell Stock III, Binary Tree Maximum Path Sum

Populating Next Right Pointers in Each Node II
Follow up for problem "Populating Next Right Pointers in Each Node".
What if the given tree could be any binary tree? Would your previous solution still work?
Note:
  • You may only use constant extra space.
For example,
Given the following binary tree,

         1
       /  \
      2    3
     / \    \
    4   5    7
After calling your function, the tree should look like:

         1 -> NULL
       /  \
      2 -> 3 -> NULL
     / \    \
    4-> 5 -> 7 -> NULL
-----------------------------------------------------------------------
Same exact solution to #116 Populating Next Right Pointers in Each Nod
/**
 * Definition for binary tree with next pointer.
 * struct TreeLinkNode {
 *  int val;
 *  TreeLinkNode *left, *right, *next;
 *  TreeLinkNode(int x) : val(x), left(NULL), right(NULL), next(NULL) {}
 * };
 */
class Solution {
public:
    void travese (TreeLinkNode* root, vector<TreeLinkNode*> &tails, int level) {
        if (root == NULL) {
            return;
        }
        if (tails.size() < level) {
            tails.push_back(root);
        }else {
            tails[level - 1]->next = root;
            tails[level - 1] = root;
        }
        travese(root->left,tails,level + 1);
        travese(root->right,tails,level + 1);
    }

    void connect(TreeLinkNode *root) {
        vector<TreeLinkNode*> tails;
        travese(root,tails,1);
    }
};
Update Feb-19-2015
constant space
/**
 * Definition for binary tree with next pointer.
 * struct TreeLinkNode {
 *  int val;
 *  TreeLinkNode *left, *right, *next;
 *  TreeLinkNode(int x) : val(x), left(NULL), right(NULL), next(NULL) {}
 * };
 */
class Solution {
public:
    void connect(TreeLinkNode *root) {
        while (root) {
            TreeLinkNode *cur = root, *pre = NULL, *nextLevel = NULL;
            
            while (cur) {
                if (cur->left != NULL) {
                    if (nextLevel == NULL) nextLevel = cur->left;
                    if (pre == NULL) pre = cur->left;
                    else {
                        pre->next = cur->left;
                        pre = cur->left;
                    }
                }
                
                if (cur->right != NULL) {
                    if (nextLevel == NULL) nextLevel = cur->right;
                    if (pre == NULL) pre = cur->right;
                    else {
                        pre->next = cur->right;
                        pre = cur->right;
                    }
                }
                
                cur = cur->next;
            }
            root = nextLevel;
        }
    }
};
Best Time to Buy and Sell Stock III
Say you have an array for which the ith element is the price of a given stock on day i.
Design an algorithm to find the maximum profit. You may complete at most two transactions.
Note:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
------------------------------------------------------------------------------------------
DP
Divide prices[] in two parts, each which is solved as in #121 Best Time to Buy and Sell Stock
the max profit would be the largest value of  firstPart[i] + secondPart[i]
class Solution {
public:
    int maxProfit(vector<int> &prices) {
        if (prices.size() == 0) return 0;
        vector<int> dp1(prices.size(),0);
        vector<int> dp2 = dp1;
        
        int minimun = prices[0];
        for (int i = 1; i < prices.size(); i++) {
            dp1[i] = max(dp1[i - 1], prices[i] - minimun);
            minimun = min(prices[i],minimun);
        }
        
        int maximum = prices.back();
        for (int i = prices.size() - 2; i >= 0; i--) {
            dp2[i] = max(dp2[i + 1], maximum - prices[i]);
            maximum = max(prices[i],maximum);
        }
        
        int maxProfit = 0;
        for (int i = 0; i < prices.size(); i++) {
            maxProfit = max(dp1[i] + dp2[i],maxProfit);
        }
        return maxProfit;
    }
};
Binary Tree Maximum Path Sum
Given a binary tree, find the maximum path sum.
The path may start and end at any node in the tree.
For example:
Given the below binary tree,
       1
      / \
     2   3
Return 6.
--------------------------------------------------------------------------
Two scenarios:
1) Current node is the root(top) node of the path
2) Current node is in either left or right sub-tree of the path
Hence, according to the 1st, we have to include the sum of both left and right sub-trees when we calculate maximum. In another word, we produce its maximum value for each node in binary tree. But according to the 2nd, return back to upper level in recursive stack with only one or non of sub-trees.  
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int pathSum(TreeNode *root,int &maximumPath) {
        if (root == NULL) {
            return INT_MIN;
        }
        
        int leftSum = max(0,pathSum(root->left,maximumPath));
        int rightSum = max(pathSum(root->right,maximumPath),0);
        
        maximumPath = max(maximumPath,leftSum + rightSum + root->val);
        return max(leftSum,rightSum) + root->val;
    }

    int maxPathSum(TreeNode* root) {
        int m = INT_MIN;
        pathSum(root,m);
        return m;
    }
};


另一种写法
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int helper(TreeNode *root,int *sum) {
        if  (root == NULL) {
            *sum = 0;
            return INT_MIN;
        }
        
        int ls = 0, rs = 0;
        int leftM = helper(root->left,&ls);
        int rightM = helper(root->right,&rs);
        
        ls = max(ls,0);
        rs = max(rs,0);
        *sum = max(ls,rs) + root->val;
        
        return max(ls + rs + root->val, max(leftM,rightM));
    }


    int maxPathSum(TreeNode* root) {
        int sum = 0;
        return helper(root,&sum);
    }
};

Wednesday, December 25, 2013

Day 65 - 1, #89, #90, #94, Gray Code, Subsets II, Binary Tree Inorder Traversal

Gray Code
The gray code is a binary numeral system where two successive values differ in only one bit.
Given a non-negative integer n representing the total number of bits in the code, print the sequence of gray code. A gray code sequence must begin with 0.
For example, given n = 2, return [0,1,3,2]. Its gray code sequence is:
00 - 0
01 - 1
11 - 3
10 - 2
Note:
For a given n, a gray code sequence is not uniquely defined.
For example, [0,2,3,1] is also a valid gray code sequence according to the above definition.
For now, the judge is able to judge based on one instance of gray code sequence. Sorry about that.
---------------------------------------------------------------------------------
Solution#1, see patterns below

class Solution {
public:
    vector<int> grayCode(int n) {
        vector<int> ret;
        ret.push_back(0);
        for (int i = 0; i < n; i++) {
            int size = ret.size();
            int bit = 1 << i;
            for (int j = size - 1; j >= 0; j--) {
                ret.push_back(ret[j] + bit);
            }
        }
        return ret;
    }
};
Solution#2, from internet
class Solution {
public:
    vector<int> grayCode(int n) {
        vector<int> ret;
        int count = 0x01 << n;
        for(int i = 0 ; i < count; ++i) {
            ret.push_back(i ^ (i>>1));
        }
        return ret;
    }
};
Subsets II
Given a collection of integers that might contain duplicates, S, return all possible subsets.
Note:

  • Elements in a subset must be in non-descending order.
  • The solution set must not contain duplicate subsets.
For example,
If S = [1,2,2], a solution is:
[
  [2],
  [1],
  [1,2,2],
  [2,2],
  [1,2],
  []
]
----------------------------------------------------------
Solution #1. Similar to #78 Subsets
Add a hashset to skip duplicates
class Solution {
public:
    void subsets(vector<int> S, vector<vector<int> > &ret, vector<int> cur) {
        int length = S.size();
        unordered_set<int> mapping;
        for (int i = 0; i < length; i++) {
            vector<int> temp = cur;
            int head = S[0];
            S.erase(S.begin());
            if (mapping.find(head) == mapping.end()) {
                mapping.insert(head);
                temp.push_back(head);
                ret.push_back(temp);
                subsets(S,ret,temp);
            }
        }
    }

    vector<vector<int> > subsetsWithDup(vector<int> &S) {
        sort(S.begin(),S.end());
        vector<vector<int> > ret;
        vector<int> cur;
        ret.push_back(cur);
        subsets(S,ret,cur);
        return ret;
    }
};
Update Nov-19-2014
Solution#2 iterative
如果 不重复,从头插。
如果是重复数字,只需插入到前一次所插入的数列中

class Solution {
public:
    vector<vector<int> > subsetsWithDup(vector<int> &S) {
        vector<int> empty;
        vector<vector<int> > rt;
        rt.push_back(empty);
        sort(S.begin(),S.end());
        
        int size = 0;
        for (int i = 0; i < S.size(); i++) {
            int start = 0;
            if (i > 0 && S[i] == S[i - 1]) {
                start = size;
            }
            
            size = rt.size();
            for (; start < size; start++) {
                vector<int> temp = rt[start];
                temp.push_back(S[i]);
                rt.push_back(temp);
            }
        }
         
        return rt;
    }
};
Java, 递归,去重
class Solution {
    public List<List<Integer>> subsetsWithDup(int[] nums) {
        Arrays.sort(nums);
        List<List<Integer>> rt = new ArrayList<>();
        dfs(rt, nums, 0, new ArrayList<>());
        
        return rt;
    }
    
    private void dfs(List<List<Integer>> rt, int[] nums, int index, List<Integer> sofar) {
        rt.add(sofar);
        
        for (int i = index; i < nums.length; i++) {
            if (i > index && nums[i] == nums[i - 1]) continue;
            List<Integer> tmp = new ArrayList<>(sofar);
            tmp.add(nums[i]);
            dfs(rt, nums, i + 1, tmp);
        }
    }
}
迭代
class Solution {
    public List<List<Integer>> subsetsWithDup(int[] nums) {
        List<List<Integer>> rt = new ArrayList<>();
        rt.add(new ArrayList<Integer>());
        Arrays.sort(nums);
        
        int lastSize = 0;
        for (int i = 0; i < nums.length; i++) {
            List<List<Integer>> rt_tmp = new ArrayList<>();
            
            int size = rt.size();
            if (i > 0 && nums[i] == nums[i - 1]) {
                size = lastSize;
            }
                
            for (int j = size; j > 0; j--) {
                int index = rt.size() - j;
                List<Integer> inner = new ArrayList<>(rt.get(index));
                inner.add(nums[i]);
                rt_tmp.add(inner);
            }
            lastSize = rt_tmp.size();
            rt.addAll(rt_tmp);
        }
        
        return rt;
    }
}

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

   1
    \
     2
    /
   3
return [1,3,2].
Note: Recursive solution is trivial, could you do it iteratively?
-----------------------------------------------
Iterative approach
Solution #1, add a boolean value to indicate visited status
Other solutions:   

http://leetcode.com/2010/04/binary-search-tree-in-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> inorderTraversal(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->left,false));
                }else {
                    ret.push_back(p.first->val);
                    s.pop();
                    s.push(make_pair(p.first->right,false));
                }
            }else {
                s.pop();
            }
        }
        return ret;
    }
};
Update Nov-19-2014
basic idea: when a node is traversed for the second time, its value will be printed
当每一个node的左节点为NULL时,则需要打印这个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> inorderTraversal(TreeNode *root) {
        stack<TreeNode *> st;
        vector<int> rt;
        
        while (!st.empty() || root != NULL) {
            if (root) {
                st.push(root);
                root = root->left;
            }else {
                rt.push_back(st.top()->val);
                root = st.top()->right;
                st.pop();
            }
        }
        return rt;
    }
};
*表示怀疑*方法三,用2个stack,一个用来存第一次visit的node,一个是第二次visit的node

方法四,Threaded binary tree. O(n) time, O(1) space 每往左走一个node,把之前node贴在它左子树的最右下角, 这是根据inorder traversal的特性决定的。算法见leetcode
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List inorderTraversal(TreeNode root) {
        List rt = new ArrayList<>();
        TreeNode cur = root;
        
        while (cur != null) {
            if (cur.left != null) {
                root = cur;
                cur = cur.left;
                TreeNode rightMost = cur;
                
                while (rightMost.right != null) {
                    rightMost = rightMost.right;
                }
                
                rightMost.right = root;
                root.left = null;
                
            }else {
                rt.add(cur.val);
                cur = cur.right;
            }
        }
        
        return rt;
    }
}

Friday, December 20, 2013

Day 60, #51, #52, #54, N-Queens, N-Queens II, Spiral Matrix

N-Queens
The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other.

Given an integer n, return all distinct solutions to the n-queens puzzle.
Each solution contains a distinct board configuration of the n-queens' placement, where 'Q' and '.' both indicate a queen and an empty space respectively.
For example,
There exist two distinct solutions to the 4-queens puzzle:
[
 [".Q..",  // Solution 1
  "...Q",
  "Q...",
  "..Q."],

 ["..Q.",  // Solution 2
  "Q...",
  "...Q",
  ".Q.."]
]
----------------------------------------------------------------------
Typical DFS. Set up 3 vector<bool>s to indicate conflict
Red is backslash
Blue is slash
Green is row


class Solution {
public:
    void queens(vector<vector<string> > &ret,vector<bool> &slash, vector<bool> &backslash, vector<bool> &usedRow, vector<string> cur, int col, int n) {
        if (col == n) {
            ret.push_back(cur);
            return;
        }

        for (int row = 0; row < n; row++) {

            // check conflicts in diagonals and same row
            if (slash[col + row] && backslash[row-col + n] && usedRow[row]) {
                cur[row][col] = 'Q';
                slash[col + row] = false;
                backslash[row-col + n] = false;
                usedRow[row] = false;
                queens(ret,slash,backslash,usedRow,cur,col+1,n);
                
                // backtrack
                cur[row][col] = '.';
                slash[col + row] = true;
                backslash[row-col + n] = true;
                usedRow[row] = true;
            }
        }
    }

    vector<vector<string> > solveNQueens(int n) {
        vector<vector<string> > ret;
        vector<bool> slash(n*2,true);
        vector<bool> backslash(n*2,true);
        vector<bool> usedRow(n,true);
        
        // populate vectors
        string str = "";
        for (int i = 0; i < n; i++) {
            char c = '.';
            str += c;
        }
        vector<string> cur(n,str);
        
        queens(ret,slash,backslash,usedRow,cur,0,n);
        return ret;
    }
};
Update Feb-10-2015
Using bit operation
class Solution {
public:
    string getString(int n, int p) {
        string s(n,'.');
        s[p] = 'Q';
        return s;
    }

    void queens(vector<vector<string> > &rt, vector<string> cur,int slash, int backSlash, int row, int n) {
        int upperLimit = (1 << n) - 1;
        if (row == upperLimit) {
            rt.push_back(cur);
            return;
        }
        
        int possiblePositions = upperLimit & (~(slash | backSlash | row));
        int itr = possiblePositions;
        int p = n - 1;
        while (possiblePositions != 0) {
            int rightMost = possiblePositions & (-possiblePositions);
            if (itr & 1) {
                string s = getString(n,p);
                vector<string> temp = cur;
                temp.push_back(s);
                possiblePositions -= rightMost;
                
                queens(rt,temp,(slash + rightMost) << 1,(backSlash + rightMost) >> 1,row + rightMost,n);
            }
            p--;
            itr >>= 1;
        }
    }

    vector<vector<string> > solveNQueens(int n) {
        vector<vector<string> > rt;
        vector<string> cur;
        queens(rt,cur,0,0,0,n);
        
        return rt;
    }
};

Java, updated on Sep-8th-2018
O(n!)
T(n) = n * T(n - 1)

class Solution {
    public List> solveNQueens(int n) {
        boolean[] cols = new boolean[n];
        boolean[] diag = new boolean[n * 2]; // row + col
        boolean[] antiDiag = new boolean[n * 2]; // row - col + n - 1
        
        List> rt = new ArrayList<>();
        dfs(0, n, new ArrayList(), rt, cols, diag, antiDiag);
        
        return rt;
    }
    
    private void dfs(int row, int n, List sofar, List> rt,
                    boolean[] cols, boolean[] diag, boolean[] antiDiag) {
        
        if (row >= n) {
            rt.add(sofar);
            return;
        }
                
        String cur = "";
        for (int i = 0; i < n; i++) {
            if (!cols[i] && !diag[row + i] && !antiDiag[row - i + n - 1]) {
                cols[i] = true;
                diag[row + i] = true;
                antiDiag[row - i + n - 1] = true;
            
                String tmp = cur + "Q";
                for (int j = i + 1; j < n; j++) tmp += "."; 
                List tmpSofar = new ArrayList<>(sofar);
                tmpSofar.add(tmp);
                
                dfs(row + 1, n, tmpSofar, rt, cols, diag, antiDiag);
                
                cols[i] = false;
                diag[row + i] = false;
                antiDiag[row - i + n - 1] = false;
            }
            
            cur += ".";
        }
    }
}

N-Queens II
Follow up for N-Queens problem.
Now, instead outputting board configurations, return the total number of distinct solutions.
---------------------------------------------------------------------
Solution #1 similar to previous problem
Note that usedRow[row] should be checked first otherwise it exceeds OJ's  time limit
class Solution {
public:
void queens(int &ret,vector<bool> &slash, vector<bool> &backslash, vector<bool> &usedRow, int col, int n) {
        if (col == n) {
            ret++;
            return;
        }

        for (int row = 0; row < n; row++) {
            if (usedRow[row] && slash[col + row] && backslash[row-col + n]) {
                slash[col + row] = false;
                backslash[row-col + n] = false;
                usedRow[row] = false;
                queens(ret,slash,backslash,usedRow,col+1,n);
                
                // backtrack
                slash[col + row] = true;
                backslash[row-col + n] = true;
                usedRow[row] = true;
            }
        }
    }

    int totalNQueens(int n) {
        vector<bool> slash(n*2,true);
        vector<bool> backslash(n*2,true);
        vector<bool> usedRow(n,true);
        
        int ret = 0;
        queens(ret,slash,backslash,usedRow,0,n);
        return ret;
    }
};
Solution #2
http://www.matrix67.com/blog/archives/266  

Update on Nov-13-2014 
基本思路为DFS
~(row | slash | backSlash) 代表每行上的可放位置,当切入到下一行时,slash跟backSlash分别需要位移一位
possiblePosition 代表当前行所有可放入棋子的位置
rightMostOne 代表当前放入棋子的位置
拿一个例子走一遍代码,立即能明白此算法
class Solution {
public:
    void bitOP(int &num, int row, int slash, int backSlash, int n) {
        int upperLimit = (1 << n) - 1; // upperLimit has n of '1'
        if (row == upperLimit) {
            num++;
            return;
        }
        
        int possiblePosition = upperLimit & (~(row | slash | backSlash)); // get posiible positions for queen in a row
        while (possiblePosition != 0) {
            int rightMostOne = possiblePosition & (-possiblePosition); // get the most right '1' as new queen's position
            possiblePosition -= rightMostOne;
            bitOP(num, row + rightMostOne, (slash + rightMostOne) << 1, (backSlash + rightMostOne) >> 1,n);
        }
        
    }

    int totalNQueens(int n) {
        int num = 0;
        bitOP(num,0,0,0,n);
        return num;
    }
};
Spiral Matrix
Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order.
For example,
Given the following matrix:
[
 [ 1, 2, 3 ],
 [ 4, 5, 6 ],
 [ 7, 8, 9 ]
]
You should return [1,2,3,6,9,8,7,4,5].
-----------------------------------------------------------
Similar to #59, Spiral Matrix II
start at the outer most layer
class Solution {
public:
    void spiral (vector<vector<int> > &matrix, vector<int> &ret, int m, int n, int k) {
        if (m <= 0 || n <= 0) {
            return;
        }
        
        if (m == 1) {
            for (int i = 0; i < n; i++) {
                ret.push_back(matrix[k][k + i]);
            }
            return;
        }
        
        if (n == 1) {
            for (int i = 0; i < m; i++) {
                ret.push_back(matrix[k + i][k]);
            }
            return;
        }
        
        // going right
        for (int i = 0; i < n - 1; i++) {
            ret.push_back(matrix[k][i + k]);    
        }
        
        // going down
        for (int i = 0; i < m - 1; i++) {
            ret.push_back(matrix[k + i][n - 1 + k]);
        }
        
        // going left
        for (int i = 0; i < n - 1; i++ ) {
            ret.push_back(matrix[m - 1 + k][n - 1 + k - i]);
        }
        
        // going up
        for (int i = 0; i < m - 1; i++ ) {
            ret.push_back(matrix[k + m - 1 - i][k]);
        }
        
        spiral(matrix,ret,m-2,n-2,k+1);
    }

    vector<int> spiralOrder(vector<vector<int> > &matrix) {
        int m = matrix.size();
        vector<int> ret;
        if (m == 0) return ret;
        int n = matrix[0].size();
        spiral(matrix,ret,m,n,0);
        return ret;
    }
};

Saturday, October 12, 2013

Day 49, #127, #131, Word Ladder, Palindrome Partitioning

Word Ladder
Given two words (start and end), and a dictionary, find the length of shortest transformation sequence from start to end, such that:
  1. Only one letter can be changed at a time
  2. Each intermediate word must exist in the dictionary
For example,
Given:
start = "hit"
end = "cog"
dict = ["hot","dot","dog","lot","log"]

As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
return its length 5.
Note:

  • Return 0 if there is no such transformation sequence.
  • All words have the same length.
  • All words contain only lowercase alphabetic characters.
------------------------------------------------------------------------
typical BFS and shortest path
class Solution {
public:
    int ladderLength(string start, string end, unordered_set<string> &dict) {
        // Note: The Solution object is instantiated only once and is reused by each test case.
        if (start == end) return 1;
        queue<pair<string,int> > q;
        q.push(make_pair(start, 1)); // assign each node a distance
        unordered_set<string> used;
        while (!q.empty()) {
            string top = q.front().first;
            int length = q.front().second;
            q.pop();
            for (int index = 0; index < start.length(); index++ ) {
                for (int alp = 'a'; alp < 'z'; alp++) {
                    if (alp == top[index]) continue; // ignore the same letter
                    string temp = top;
                    temp[index] = alp;
                    if (temp == end) {
                        return length+1;
                    }
                    if (used.find(temp) == used.end() && dict.find(temp) != dict.end()) {
                        used.insert(temp);
                        q.push(make_pair(temp, length+1));
                    }
                    
                }
            }
        }
        return 0;
    }
};
Java,双向BFS, udpated on Aug-4th-2018
class Solution {
    public int ladderLength(String beginWord, String endWord, List<String> wordList) {
        int len = 1;
        Map<String, Boolean> dic = getDic(wordList);
        if (!dic.containsKey(endWord)) return 0;
        
        dic.put(beginWord, false);
        dic.put(endWord, false);
        Set<String> begin = new HashSet<>();
        Set<String> end = new HashSet<>();
        begin.add(beginWord);
        end.add(endWord);
        
        while (!begin.isEmpty() && !end.isEmpty()) {
            if (begin.size() > end.size()) {
                Set<String> t = begin;
                begin = end;
                end = t;
            }
            
            len++;
            Set<String> temp = new HashSet<>();
            for (String s : begin) {
                for (int i = 0; i < s.length(); i++) {
                    char c = s.charAt(i);
                    for (char nextC = 'a'; nextC <= 'z'; nextC++) {
                        String next = s.substring(0, i) + nextC + s.substring(i + 1);

                        if (end.contains(next)) return len;

                        if (dic.containsKey(next) && dic.get(next)) {
                            temp.add(next);
                            dic.put(next, false);
                        }
                    }
                }
            }
            
            begin = temp;
        }
        
        return 0;
    }
    
    private Map<String, Boolean> getDic(List<String> wordList) {
        Map<String, Boolean> dic = new HashMap<>();
        
        for (String s : wordList) {
            dic.put(s, true);
        }
        
        return dic;
    }
}
Palindrome Partitioning
Given a string s, partition s such that every substring of the partition is a palindrome.
Return all possible palindrome partitioning of s.
For example, given s = "aab",
Return
  [
    ["aa","b"],
    ["a","a","b"]
  ]
-----------------------------------------
DFS, recursive
class Solution {
public:
    bool checkPalin (string s) {
        for (int i = 0; i < s.length()/2; i++) {
            int end = s.length() - 1 - i;
            if (s[i] != s[end]) {
                return false;
            }
        }
        return true;
    }
    
    void partition (string cur, vector<string> v, string remain,  vector<vector<string> >& ret) {
        if (remain.empty()) {
            ret.push_back(v);
            return;
        }
        
        for (int i = 0; i < remain.length(); i++) {
            cur += remain[i];
            if (checkPalin(cur)) {
                vector<string> cp = v; 
                cp.push_back(cur);
                partition("",cp,remain.substr(i+1),ret);
            }
        }
    }
    
    vector<vector<string>> partition(string s) {
        // Note: The Solution object is instantiated only once and is reused by each test case.
        vector<vector<string> > ret;
        vector<string> v;
        partition("",v,s,ret);
        return ret;
    }
};
Update on Oct-03-2014
Using index
class Solution {
public:
    bool isPal(string str) {
        for (int i = 0; i < str.length() / 2; i++) {
            if (str[i] != str[str.length() - 1 - i]) {
                return false;
            }
        }
        
        return true;
    }
    
    void dfs(vector<vector<string> > &rt, vector<string> cur, string s,int index) {
        if (index == s.length()) {
            rt.push_back(cur);
            return;
        }
        for (int i = 1; i < s.length() - index + 1; i++) {
            string sub = s.substr(index,i);    
            if (isPal(sub)) {
                vector<string> temp = cur;
                temp.push_back(sub);
                dfs(rt,temp,s,index + i);
            }
        }
    
    }
    
    vector<vector<string>> partition(string s) {
        vector<vector<string> > rt;
        vector<string> v;
        dfs(rt,v,s,0);
        return rt;
    }
};
Thoughts: we can add Memoization to improve efficiency. Set up a 2d-array of vector<vector<string> >, [i][j] contains all palindrome partitionings between i and j

Friday, October 11, 2013

Day 47, #105, #106, #107, #114 Construct Binary Tree from Preorder and Inorder Traversal, Construct Binary Tree from Inorder and Postorder Traversal, Binary Tree Level Order Traversal II, Flatten Binary Tree to Linked List

Construct Binary Tree from Preorder and Inorder Traversal
Given preorder and inorder traversal of a tree, construct the binary tree.
Note:
You may assume that duplicates do not exist in the tree.
-----------------------------------------------
Explaination 
Having a start and an end pointer for each array.
Using hash table to track the root position in inorder array.
For preorder array, the first in partition is always the root node, for inorder one, in a given partition, all nodes whose indexes are less than root's are belong to its left child, whose indexes are greater than root's, belongs to its right child
Same algorithm for Postorder and Inorder combination

/**
 * 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 hashMapping(vector<int> &inorder, unordered_map<int,int>& mapping){
        for (int i = 0; i < inorder.size(); i++) {
            int k = inorder[i];
            mapping[k] = i;
        }
    }
    
    TreeNode *rec(vector<int> &preorder, vector<int> &inorder, int startP, int endP, int startI, int endI,unordered_map<int,int>& mapping) {
        //if (endI < startI || endP < startP)return NULL;
        int rootIndex = mapping[preorder[startP]];
        TreeNode *root = new TreeNode(preorder[startP]);
        // delimiter for preorder
        int delimiterIndex = rootIndex - startI + startP; 
        if (rootIndex > startI) {
            root->left = rec(preorder,inorder,startP+1,delimiterIndex,startI,rootIndex - 1,mapping);
        }else {
            root->left=NULL;
        }
        if (rootIndex < endI) {
            root->right = rec(preorder,inorder,delimiterIndex + 1,endP,rootIndex + 1,endI,mapping);
        }else {
            root->right=NULL;
        }
        return root;
    }
    
    TreeNode *buildTree(vector<int> &preorder, vector<int> &inorder) {
        // Note: The Solution object is instantiated only once and is reused by each test case.
        if (preorder.size() == 0) return NULL;
        unordered_map<int,int> mapping;
        hashMapping(inorder,mapping);
        return rec(preorder,inorder,0,preorder.size()-1,0,inorder.size()-1,mapping);
    }
};
Construct Binary Tree from Inorder and Postorder Traversal
Given inorder and postorder traversal of a tree, construct the binary tree.
Note:
You may assume that duplicates do not exist in the tree.
-----------------------------
Similar to Preorder and Inorder combination
/**
 * 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 hashMapping(vector<int> &inorder, unordered_map<int,int>& mapping){
        for (int i = 0; i < inorder.size(); i++) {
            int k = inorder[i];
            mapping[k] = i;
        }
    }

    TreeNode *rec(vector<int> &postorder, vector<int> &inorder, int startP, int endP, int startI, int endI,unordered_map<int,int>& mapping) {
        //if (endI < startI || endP < startP)return NULL;
        int rootIndex = mapping[postorder[endP]];
        TreeNode *root = new TreeNode(postorder[endP]);
        // delimiter for postorder
        int delimiterIndex = rootIndex - startI + startP-1; 
        if (rootIndex > startI) {
            root->left = rec(postorder,inorder,startP,delimiterIndex,startI,rootIndex - 1,mapping);
        }else {
            root->left=NULL;
        }
        if (rootIndex < endI) {
            root->right = rec(postorder,inorder,delimiterIndex + 1,endP-1,rootIndex + 1,endI,mapping);
        }else {
            root->right=NULL;
        }
        return root;
    }

    TreeNode *buildTree(vector<int> &inorder, vector<int> &postorder) {
        // Note: The Solution object is instantiated only once and is reused by each test case.
        if (postorder.size() == 0) return NULL;
        unordered_map<int,int> mapping;
        hashMapping(inorder,mapping);
        return rec(postorder,inorder,0,postorder.size()-1,0,inorder.size()-1,mapping);
    }
};
Binary Tree Level Order Traversal II
Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from left to right, level by level from leaf to root).
For example:
Given binary tree {3,9,20,#,#,15,7},

    3
   / \
  9  20
    /  \
   15   7
return its bottom-up level order traversal as:

[
  [15,7]
  [9,20],
  [3],
] 
----------------------------------
Similar to #102 Binary Tree Level Order Traversal
This is a DFS solution 
 
/**
 * 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<vector<int> > levelOrderBottom(TreeNode *root) {
    // Start typing your C/C++ solution below
    // DO NOT write int main() function
    vector<vector<int>> result;
    traverse(root, 1, result);
    std::reverse(result.begin(), result.end());
    return result;
}

void traverse(TreeNode *root, int level, vector<vector<int>> &result) {
    if (root == NULL) {
        return;
    }
    
    if (level > result.size()) {
        vector<int> v;
        result.push_back(v);
    }
    
    result[level-1].push_back(root->val);
    traverse(root->left,level+1,result);
    traverse(root->right,level+1,result);
}
};

Flatten Binary Tree to Linked List
Given a binary tree, flatten it to a linked list in-place.
For example,
Given
         1
        / \
       2   5
      / \   \
     3   4   6
The flattened tree should look like:
   1
    \
     2
      \
       3
        \
         4
          \
           5
            \
             6
----------------------------------------------------------
Solution #1, not in place, preorder traverse the tree, store each node in an array,

/**
 * 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 traverse (TreeNode *root, vector<TreeNode*>& v) {
        if (root != NULL) {
            v.push_back(root);
            traverse(root->left,v);
            traverse(root->right,v);
        }
    }

    void flatten(TreeNode *root) {
        // Note: The Solution object is instantiated only once and is reused by each test case.
        vector<TreeNode*> v;
        traverse(root,v);
        TreeNode *itr = root;
        for (int i = 1; i < v.size(); i++) {
            itr->right = v[i];
            itr->left = NULL;
            itr = itr->right;
        }
    }
};
Solution #2, in place iterative.
Same logic can be adopted in recursive implementation
O(n), 在inner loop里面,在整段代码的执行过程中每个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:
    void flatten(TreeNode *root) {
        // Note: The Solution object is instantiated only once and is reused by each test case.
        TreeNode* ret = root;
        while (root != NULL) {
            if (root->left != NULL) {
                TreeNode *right = root->right;
                TreeNode *mostRight = root->left;
                
                while (mostRight->right != NULL) {
                    mostRight = mostRight->right;
                }
                mostRight->right = right;
                root->right = root->left;
                root->left = NULL;
            }
            root = root->right;
        }
        root = ret;
    }
};
Update on Sep-28-2014
Recursive solution, Pre-Order tree 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:
    TreeNode* f(TreeNode *root, TreeNode *newRoot) {
        if (root == NULL) return newRoot;
        TreeNode *tempRight = root->right;
        newRoot->right = root;
        
        TreeNode *t = f(root->left,root); // return the end of list
        root->left = NULL;
        TreeNode *t2 = f(tempRight,t);
        return t2;
    }

    void flatten(TreeNode *root) {
        TreeNode *newRoot = root;
        TreeNode *dummy = new TreeNode(0);

        f(newRoot,dummy);
    }
};

Updated on Sep-24th-2018
跟上面类似思路,更易懂的写法。getEndOfList(root)返回以root为顶点的sub-tree转换成为list之后的最尾端的点
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {

    public void flatten(TreeNode root) {
        if (root == null) return;
        getEndOfList(root);
    }
    
    private TreeNode getEndOfList(TreeNode root) {

        TreeNode l = root.left;
        TreeNode r = root.right;
        if (root.left != null) {
            TreeNode end = getEndOfList(root.left);
            root.right = l;
            l = end;
            end.right = r;
            root.left = null;
        }
        
        if (r != null) {
            return getEndOfList(r);
        }
        if (l == null) {
            return root;
        }
        return l;   
    }
}

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

Monday, August 26, 2013

Day 41, 91 Decode Ways

Decode Ways
A message containing letters from A-Z is being encoded to numbers using the following mapping:
'A' -> 1
'B' -> 2
...
'Z' -> 26
Given an encoded message containing digits, determine the total number of ways to decode it.
For example,
Given encoded message "12", it could be decoded as "AB" (1 2) or "L" (12).
The number of ways decoding "12" is 2.
------------------------------------------------
similar to steps problem, with some extra conditions
Solution #1 simple recursion
class Solution {
public:
    int numDecodings(string s) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if (s.length() == 0 || s[0] == '0') return 0;
        if (s.length() == 1) return 1;
        int fix = 0;
        if (s.length() == 2) {
            fix = 1;
        }
        if (s[0] == '1' || (s[0] == '2' && s[1] < '7')) {
            return numDecodings(s.substr(1)) + numDecodings(s.substr(2)) + fix;
        }
        return numDecodings(s.substr(1));
    }
};
Solution #2 DP
class Solution {
public:
    int numDecodings(string s) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if (s.length() == 0 || s[0] == '0') {
            return 0;
        }
        vector<int> ways(s.length() + 1, 1);
        for (int i = s.length() - 1; i >= 0; i--) {
            if (s[i] == '0') {
                ways[i] = 0;
            }else {
                ways[i] = ways[i+1];
            }
            if (i+1 < s.length() && (s[i] == '1' || (s[i] == '2' && s[i+1] < '7'))) {
                ways[i] += ways[i+2];
            }
        }
        return ways[0];
    }
};

In Java, recursion with memoization
class Solution {
    private Map<String, Integer> map = new HashMap<>();
    public int numDecodings(String s) {
        if (s.length() == 0 || s.charAt(0) == '0') return 0;
        if (s.length() == 1) {
            return 1;
        }
        
        int i = 0;
        String s1 = s.substring(1);
        if (map.containsKey(s1)) {
            i = map.get(s1);
        }else {
            i = numDecodings(s.substring(1)); 
            map.put(s.substring(1), i);
        }
        
        if (s.charAt(0) == '1' || (s.charAt(0) == '2' && s.charAt(1) < '7')) {
            
            String s2 = s.substring(2);
            int j = 0;
            
            if (map.containsKey(s2)) {
                j = map.get(s2);
            }else {
                j = numDecodings(s2); 
                map.put(s2, j);
            }
            
            int rt = 0;
            if (s.length() == 2) rt = 1;
            return i + j + rt;
        }
        
        return i;
    }
}

COME_BACK
写一下O(1) 空间复杂度

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