Thursday, September 19, 2013

Day 45, #98 Validate Binary Search Tree

Validate Binary Search Tree
Given a binary tree, determine if it is a valid binary search tree (BST).
Assume a BST is defined as follows:
  • The left subtree of a node contains only nodes with keys less than the node's key.
  • The right subtree of a node contains only nodes with keys greater than the node's key.
  • Both the left and right subtrees must also be binary search trees.
---------------------------------------------------
Perform an in-order tree traversal, save all values in an array, and later check if it is sorted
There is room for space optimization in solution below
/**
 * 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 rec (TreeNode *root, vector<int> &v) {
        if (root->left != NULL) {
            rec(root->left,v);
        }
        v.push_back(root->val);
        if (root->right != NULL) {
            rec(root->right,v);
        }
    }

    bool isValidBST(TreeNode *root) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if (root == NULL) return true; 
        vector<int> v;
        rec(root,v);
        if (v.size() < 2) {
            return true;
        }
        // check if it's already sorted
        for (int i = 1; i < v.size(); i++) {
            if (v[i-1] >= v[i]) {
                return false;
            }
        }
        return true;
    }
};
Update: Jan-16-2014
http://leetcode.com/2010/09/determine-if-binary-tree-is-binary.html
Solution#2, in space.
Note int &pre in arguments
/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool inorder (TreeNode *root, int &pre) {
       if (root == NULL) {
           return true;
       }
       if (inorder(root->left,pre)) {
           if (pre >= root->val) {
               return false;
           }
           pre = root->val;
           return inorder(root->right,pre);
       }
       return false;
       
    }

    bool isValidBST(TreeNode *root) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if (root == NULL) return true; 
        int pre = INT_MIN;
        return inorder(root,pre);
    }
};

Update: Jan-15-2015
to handle INT_MIN case
/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool inorder(TreeNode *root, TreeNode *&pre) {
        if (root == NULL) {
            return true;
        }
        
        if (inorder(root->left,pre)) {
            if (pre != NULL && pre->val >= root->val) {
                return false;
            }
            pre = root;
            return inorder(root->right,pre);
            
        }
        
        return false;
    }

    bool isValidBST(TreeNode *root) {
        TreeNode *pre = NULL;
        return inorder(root,pre);
    }
};

Java, updated Jun-24th-2018
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    
    private TreeNode pre = null;
    public boolean isValidBST(TreeNode root) {
        if (root == null) return true;
        if (!isValidBST(root.left)) {
            return false;
        }
        
        if (pre == null) pre = root;
        else if (pre.val >= root.val) {
            return false;
        }
        pre = root;
        return isValidBST(root.right);
    }
}

当有node的值等于MIN_VALUE或MAX_VALUE, 这算法就搞不定了。所有还是别用了
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isValidBST(TreeNode root) {
        return helper(root, Integer.MIN_VALUE, Integer.MAX_VALUE);
    }
    
    private boolean helper(TreeNode root, int min, int max) {
        if (root == null) return true;
        if (root.val < max && root.val > min) {
            return helper(root.left, min, root.val) 
                && helper(root.right, root.val, max);
        }
        
        return false;
    }
}

Wednesday, September 11, 2013

Day 44, #96 Unique Binary Search Trees

Unique Binary Search Trees
Given n, how many structurally unique BST's (binary search trees) that store values 1...n?
For example,
Given n = 3, there are a total of 5 unique BST's.
   1         3     3      2      1
    \       /     /      / \      \
     3     2     1      1   3      2
    /     /       \                 \
   2     1         2                 3 
-------------------------------------------------
Catalan Number 
COME_BACK


class Solution {
public:
    int numTrees(int n) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        int ret = 1;
        for (int i = 2; i <= n; i++) {
            ret = 2*(2*i-1)*ret/(i+1);
        }
        return ret;
    }
};
DP
class Solution {
public:
    int numTrees(int n) {
        vector<int> dp(n + 1,0);
        dp[0] = dp[1] = 1;
        for (int i = 2; i <= n; i++) {
            for (int j = 0; j < i; j++) {
                dp[i] += dp[j] * dp[i - j - 1];
            }
        }
        return dp[n];
    }
};

Thursday, September 5, 2013

Day 43, #93 Restore IP Addresses

Restore IP Addresses
Given a string containing only digits, restore it by returning all possible valid IP address combinations.
For example:
Given "25525511135",
return ["255.255.11.135", "255.255.111.35"]. (Order does not matter)
----------------------------------------------------
DFS

class Solution {
public:
    int stringToInt (string s) {
        int num = 0;
        for (int i = 0; i < s.length(); i++) {
            num = num * 10;
            int temp  = s[i] - '0';
            num = num + temp;
        }
        return num;
    }

    void rec (string cur, string s, int count, vector<string> &ret) {
        if (s.length() == 0 && count == 4) {
            ret.push_back(cur);
        }else if (count < 4 && s.length() != 0) {
            if (count != 0) { // no '.' before the first part 
                cur = cur + ".";
            }
            string temp;
            if (s.length() >= 1) {
                temp = cur + s[0];
            rec(temp,s.substr(1),count+1,ret);
            }
            if (s.length() >= 2 && s[0] != '0') {
                temp = cur + s.substr(0,2);
            rec(temp,s.substr(2),count+1,ret);
            }
            if (s.length() >= 3 && s[0] != '0') {
                temp = cur + s.substr(0,3);
                if (stringToInt(s.substr(0,3)) < 256) {
                    rec(temp,s.substr(3),count+1,ret);
                }
            }
        }
        
    }

    vector<string> restoreIpAddresses(string s) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        vector<string> ret;
        rec("",s,0,ret);
        return ret;
        
    }
};
Update on Sep-21-2014 
Same algorithm but with index
class Solution {
public:
    void rec(vector<string> &rt, string s, int index, int count,string ip) {
        if (count == 4 && index == s.length()) {
            rt.push_back(ip);
            return;
        }
        
        if (count > 4 || index > s.length()) return;
        
        if (count != 0) {
            ip += "."; 
        }
        
        rec(rt,s,index + 1, count + 1, ip + s.substr(index,1));
        
        if (index + 1 < s.length() && s[index] != '0') {
            string sub = s.substr(index,2);
            rec(rt,s,index + 2, count + 1, ip + sub);
        }
        
        if (index + 2 < s.length() && s[index] != '0') {
            string sub = s.substr(index,3);
            if (stoi(sub) < 256) {
                rec(rt,s,index + 3, count + 1, ip + sub);
            }
        }
        
    }

    vector<string> restoreIpAddresses(string s) {
        vector<string> rt;
        if (s == "") return rt;
        rec(rt,s,0,0,"");
        
        return rt;
    }
};

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) 空间复杂度

Thursday, July 11, 2013

Day 40, 86 Partition List

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

Sunday, July 7, 2013

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

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

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

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


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

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

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

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

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

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

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


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