Sunday, December 31, 2017

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

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        int ans;
        stack<int> st;
       
        for (int i = 0; i < tokens.size(); i++) {
            if (tokens[i] != "+" && tokens[i] != "-" &&
                tokens[i] != "*" && tokens[i] != "/") {
                st.push(stoi(tokens[i]));
            } else {
                if (st.size() < 2) {
                    return -1;
                }
                int first = st.top(); st.pop();
                int second = st.top(); st.pop();
                int new_val;
                if (tokens[i] == "+") {
                    new_val = first + second;
                } else if  (tokens[i] == "-") {
                    new_val = second - first;
                } else if (tokens[i] == "*") {
                    new_val = first * second;
                } else {
                    new_val = second / first;
                }
                st.push(new_val);
            }
        }
        ans = st.top(); st.pop();
        return ans;
    }
};

Saturday, December 30, 2017

Edit Distance

Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation sequence from beginWord to endWord, such that:
  1. Only one letter can be changed at a time.
  2. Each transformed word must exist in the word list. Note that beginWord is not a transformed word.
For example,
Given:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log","cog"]
As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
return its length 5.

class Solution {
public:
    int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
        unordered_set<string> dict(wordList.begin(), wordList.end());
        queue<pair<string, int> > q;
        q.push(make_pair(beginWord, 1));

        while (!q.empty()) {
            pair<string, int> poped = q.front(); q.pop();
            if (poped.first == endWord) {
                return poped.second;
            } else {
                string poped_str = poped.first;
                for (int i = 0; i < poped_str.size(); i++) {
                    for (char ch = 'a'; ch <= 'z'; ch++) {
                        if (poped_str[i] != ch) {
                            char temp = poped_str[i];
                            poped_str[i] = ch;
                            if (dict.count(poped_str)) {
                                q.push(make_pair(poped_str, poped.second + 1));
                                dict.erase(poped_str);
                            }
                            poped_str[i] = temp;
                        }
                    }
                }
            }
        }
        return 0;
    }
};

Permutations II

Given a collection of numbers that might contain duplicates, return all possible unique permutations.
For example,
[1,1,2] have the following unique permutations:
[
  [1,1,2],
  [1,2,1],
  [2,1,1]
]
 
class Solution {
public:
    void permute(vector<int> num, int st, int end,
                 vector<vector<int> >& ans) {
        if (st == end) {
            ans.push_back(num);
        } else {
            for (int i = st; i < end; i++) {
                // Continue if num[i] exists b/w indexes [st, i].
                int iter_back = i - 1;
                bool exists = false;
                while (iter_back >= st) {
                    if (num[iter_back] == num[i]) {
                        exists = true;
                        break;
                    }
                    iter_back--;
                }
                if (exists == true) {
                    continue;
                }
                iter_swap(num.begin() + st, num.begin() + i);
                permute(num, st + 1, end, ans);
                iter_swap(num.begin() + i, num.begin() + st); 
            }
        }
    }
    vector<vector<int> > permuteUnique(vector<int> &num) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        vector<vector<int> > ans;
        if (num.size() == 0) {
            return ans;
        }
        permute(num, 0, num.size(), ans);
        return ans;
    }

};

Search for a range

Given an array of integers sorted in ascending order, find the starting and ending position of a given target value.
Your algorithm's runtime complexity must be in the order of O(log n).
If the target is not found in the array, return [-1, -1].
For example,
Given [5, 7, 7, 8, 8, 10] and target value 8,
return [3, 4].

class Solution {
public:
    int leftMost(vector<int>& nums, int target) {       
        int left = 0, right = nums.size() - 1;
        while (left <= right) {
            int mid = left + (right - left)/2;
            if (nums[mid] == target) {
                if (mid == left || nums[mid] != nums[mid - 1]) {
                    return mid;
                } else {
                    right = mid - 1;
                }
            } else if (nums[mid] < target) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return -1;
    }
   
    int rightMost(vector<int>& nums, int target) {
        int left = 0, right = nums.size() - 1;
        while (left <= right) {
            int mid = left + (right - left)/2;
            if (nums[mid] == target) {
                if (mid == right || nums[mid] != nums[mid + 1]) {
                    return mid;
                } else {
                    left = mid + 1;
                }
            } else if (nums[mid] < target) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return -1;
    }
   
    vector<int> searchRange(vector<int>& nums, int target) {
        vector<int> ans;
        ans.push_back(leftMost(nums, target));
        ans.push_back(rightMost(nums, target));
        return ans;
    }
};

Saturday, August 26, 2017

Serialize and Deserialize Binary Tree

Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another computer environment.
Design an algorithm to serialize and deserialize a binary tree. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that a binary tree can be serialized to a string and this string can be deserialized to the original tree structure.
For example, you may serialize the following tree
    1
   / \
  2   3
     / \
    4   5
as "[1,2,3,null,null,4,5]", just the same as how LeetCode OJ serializes a binary tree. You do not necessarily need to follow this format, so please be creative and come up with different approaches yourself.
Note: Do not use class member/global/static variables to store states. Your serialize and deserialize algorithms should be stateless.

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Codec {
public:
    vector<string> split(string s) {
        vector<string> split_str;
        stringstream ss(s);
        string tmp;
        while (getline(ss, tmp, ',')) {
            split_str.push_back(tmp);
        }
        return split_str;
    }

    // Encodes a tree to a single string.
    vector<string> serialize(TreeNode* root) {
        vector<string> serialized;
        string ans;
        if (root == NULL) {
            return serialized;
        }
        queue<TreeNode *> q;
        q.push(root);
        while (!q.empty()) {
            TreeNode *node = q.front(); q.pop();
            if (ans.empty()) {
                ans = to_string(node -> val);
            } else {
                ans += "," + (node != NULL ? to_string(node -> val) : "#");
            }
            if (node != NULL) {
                q.push(node -> left);
                q.push(node -> right);
            }
        }
        
        serialized = split(ans);
        int size = serialized.size() - 1;
        while (size >= 0) {
            if (serialized[size--] != "#") {
                break;
            }
            serialized.erase(serialized.begin() + size + 1);
        }
        return serialized; 
    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(vector<string> data) {
        if (data.empty()) {
            return NULL;
        }
        TreeNode *root = new TreeNode(stoi(data[0]));
        int size = data.size(), i = 1;
        queue<TreeNode *> q;
        q.push(root);
        
        while (i < size && !q.empty()) {
            TreeNode *node = q.front(); q.pop();
            if (data[i++] != "#") {
                node -> left = new TreeNode(stoi(data[i - 1]));
                q.push(node -> left);
            }
            if (data[i++] != "#") {
                node -> right = new TreeNode(stoi(data[i - 1]));
                q.push(node -> right);
            }
        }
        return root;
    }
};

// Your Codec object will be instantiated and called as such:
// Codec codec;
// codec.deserialize(codec.serialize(root));


========== Another =========
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Codec {
public:

    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        string ans;
        if (root == NULL) {
            return ans;
        }
        vector<string> sol;
        queue<TreeNode *> q;
        q.push(root);
        while (!q.empty()) {
            TreeNode *node = q.front(); q.pop();
            if (node != NULL) {
                sol.push_back(to_string(node -> val));
                q.push(node -> left);
                q.push(node -> right);
            } else {
                sol.push_back("null");
            }
        }
        
        formatResponse(ans, sol);
        return ans;
    }
    
    void formatResponse(string& ans, vector<string>& strList) {
        int size = strList.size();
        if (size == 0) {
            ans = "";
            return;
        }
        
        for (int i = size - 1; i >= 0; i--) {
            if (strList[i] == "null") {
                strList.pop_back();
            } else {
                break;
            }
        }
        
        for (int i = 0; i < strList.size(); i++) {
            if (i == 0) {
                ans += strList[i];
            } else {
                ans += "," + strList[i];
            }
        }
    }

    void split(string s, vector<string>& resp, char delim) {
        stringstream ss(s);
        string str;
        while(getline(ss, str, delim)) {
            resp.push_back(str);
        }
        return;
    }
    
    void helper(TreeNode *& root, vector<string>& input) {
        if (input.size() == 0 || input[0] == "null") {
            root = NULL;
            return;
        }
        
        root = new TreeNode(stoi(input[0]));
        queue<TreeNode *> q;
        q.push(root);
        int size = input.size();
        int iter = 1;
        while (1) {
            if (q.empty() || iter == size) {
                break;
            }
            TreeNode *node = q.front(); q.pop();
            if (input[iter] != "null") {
                node -> left = new TreeNode(stoi(input[iter]));
                q.push(node -> left);
            } else {
                node -> left = NULL;
            }
            iter++;
            if (iter == size) {
                break;
            }
            if (input[iter] != "null") {
                node -> right = new TreeNode(stoi(input[iter]));
                q.push(node -> right);
            } else {
                node -> right = NULL;
            }
            iter++;
        }
    }
    
    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        TreeNode *root = NULL;
        if (data.empty()) {
            return root;
        }
        
        vector<string> input;
        split(data, input, ',');
        
        helper(root, input);
        return root;
    }
};

// Your Codec object will be instantiated and called as such:
// Codec codec;

// codec.deserialize(codec.serialize(root));

========================
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Codec {
public:
    vector<string> split(string str) {
        stringstream ss(str);
        vector<string> ans;
        string tmp;
        while(getline(ss, tmp, ',')) {
            ans.push_back(tmp);
        }
        return ans;
    }

    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        queue<TreeNode *> q;
        if (root == NULL) {
            return "";
        }
        string ans;
        q.push(root);
        while (!q.empty()) {
            TreeNode *node = q.front(); q.pop();
            string code;
            if (node != NULL) {
                code = to_string(node -> val);
            } else {
                code = "#";
            }
            ans += (ans != "" ? "," +  code: code);
            if (node == NULL) {
                continue;
            }
            q.push(node -> left);
            q.push(node -> right);
        }
        // Check if trimming needed in the last.
        return ans;
    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        if (data == "" || data == "#") {
            return NULL;
        }
        
        vector<string> str_list = split(data);
        queue<TreeNode *> q;
        TreeNode *root = new TreeNode(stoi(str_list[0]));
        q.push(root);
        int iter = 1;
        while (iter == 0 || !q.empty()) {
            TreeNode *node = q.front(); q.pop();
            string val = str_list[iter];
            if (val != "#") {
                node -> left = new TreeNode(stoi(val));
                q.push(node -> left);
            }
            iter++;
            if (iter == str_list.size()) {
                return root;
            }
            val = str_list[iter];
            if (val != "#") {
                node -> right = new TreeNode(stoi(val));
                q.push(node -> right);
            }
            iter++;
            if (iter == str_list.size()) {
                return root;
            }
        }
        return root;
    }
};

// Your Codec object will be instantiated and called as such:
// Codec ser, deser;
// TreeNode* ans = deser.deserialize(ser.serialize(root));

Sunday, August 20, 2017

Insert interval



Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary).
You may assume that the intervals were initially sorted according to their start times.
Example 1:
Given intervals [1,3],[6,9], insert and merge [2,5] in as [1,5],[6,9].
Example 2:
Given [1,2],[3,5],[6,7],[8,10],[12,16], insert and merge [4,9] in as [1,2],[3,10],[12,16].
This is because the new interval [4,9] overlaps with [3,5],[6,7],[8,10].

============
in-place one:

vector<Interval> adjustEnd(vector<Interval>& intervals, int i, Interval newInterval) {
        int j = i + 1;
        while (j <= intervals.size()) {
            if (j == intervals.size()) {
                intervals[i].end = max(newInterval.end, intervals[i].end);
                return intervals;
            }

            if (newInterval.end < intervals[j].start) {
                intervals[i].end = max(newInterval.end, intervals[i].end);
                return intervals;
            } else if (newInterval.end >= intervals[j].start &&
                        newInterval.end <= intervals[j].end) {
                intervals[i].end = intervals[j].end;
                intervals.erase(intervals.begin() + j);
                return intervals;
            } else {
                intervals.erase(intervals.begin() + j);
            }
        }
        return intervals;
    }

    vector<Interval> insert(vector<Interval>& intervals, Interval newInterval) {
        if (intervals.size() == 0) {
            intervals.push_back(newInterval);
            return intervals;
        }
        int size = intervals.size();
        if (newInterval.start > intervals[size - 1].end) {
            intervals.push_back(newInterval);
            return intervals;
        }
        int i = 0;
        while (i < intervals.size()) {
            if (newInterval.start >= intervals[i].start &&
                newInterval.start <= intervals[i].end) {
                return adjustEnd(intervals, i, newInterval);
            } else if (newInterval.start < intervals[i].start) {
                if (newInterval.end < intervals[i].start) {
                    intervals.insert(intervals.begin() + i, newInterval);
                    return intervals;
                } else if (newInterval.end >= intervals[i].start) {
                    intervals[i].start = newInterval.start;
                    return adjustEnd(intervals, i, newInterval);
                }
            }
            i++;
        }
        
        return intervals;
    }


=============
Short and elegant below in java:


 public List<Interval> insert(List<Interval> intervals, Interval newInterval) {
    if(newInterval == null) return intervals;
    int first = 0;
    /*find first overlapping interval*/
    while(first < intervals.size() && newInterval.start > intervals.get(first).end)
        first++;   
    /*merge intervals */
    while(first < intervals.size() && newInterval.end >= intervals.get(first).start)
    {
        newInterval = new Interval(Math.min(newInterval.start,intervals.get(first).start),
                                  Math.max(newInterval.end,intervals.get(first).end));
        intervals.remove(first);
    }
    intervals.add(first,newInterval);
    return intervals;
}

===============  Recent one ========

class Solution {
public:
    bool overlap(vector<int> interval, int& first, int& second) {
        if ((first >= interval[0] && first <= interval[1]) ||
            (second >= interval[0] && second <= interval[1])) {
            
            first = min(interval[0], first);
            second = max(interval[1], second);
            return true;
        }
        return false;
    }

    vector<vector<int>> insert(vector<vector<int>>& intervals, vector<int>& newInterval) {
        vector<vector<int>> sol;
        int first = newInterval[0];
        int second = newInterval[1];
        
        if (intervals.size() == 0) {
            sol.push_back(vector<int> {first, second});
            return sol;
        }
        
        int i = 0;
        bool merged = false;
        
        for (i = 0; i < intervals.size(); i++) {
            bool is_overlap = overlap(intervals[i], first, second);
            if (!is_overlap) {
                if (second < intervals[i][0]) {
                    if (!merged) {
                        sol.push_back(vector<int> {first, second});
                        merged = true;
                    }
                    sol.push_back(intervals[i]);
                } else if (intervals[i][1] < first) {
                    sol.push_back(intervals[i]);
                }
            }
        }
        
        if (!merged) {
            sol.push_back(vector<int> {first, second});
        }
        return sol;
    }

};


=========== Another one =======
class Solution {
public:
    
    int overlap(vector<int>& newInterval, vector<int>& interval) {
        if (newInterval[1] < interval[0]) {
            // newInterval < interval
            return -1;
        } else if (newInterval[0] > interval[1]) {
            // newInterval > interval
            return 1;
        } else {
            // Merge.
            return 0;
        }
    }
    
    vector<vector<int>> insert(vector<vector<int>>& intervals, vector<int>& newInterval) {
        vector<vector<int>> sol;
        if (intervals.size() == 0) {
            sol.push_back(newInterval);
            return sol;
        }
        
        int iter = 0;
        while (iter < intervals.size()) {
            int option = overlap(newInterval, intervals[iter]);
            if (option == 0) {
                // Merge going-on
                newInterval[0] = min(newInterval[0], intervals[iter][0]);
                newInterval[1] = max(newInterval[1], intervals[iter][1]);
            } else if (option == -1) {
                // merge completed.
                sol.push_back(newInterval);
                while (iter < intervals.size()) {
                    sol.push_back(intervals[iter]);
                    iter++;
                }
                return sol;
            } else {
                // Merge ahead
                sol.push_back(intervals[iter]);
            }
            iter++;
        }
        sol.push_back(newInterval);
        return sol;
    }

};