Saturday, January 31, 2015

Day 98, ##, Maximum Gap

Maximum Gap

Given an unsorted array, find the maximum difference between the successive elements in its sorted form.
Try to solve it in linear time/space.
Return 0 if the array contains less than 2 elements.
You may assume all elements in the array are non-negative integers and fit in the 32-bit signed integer range.
------------------------------------------------------------------------------
reference 
use n - 1 buckets
注意 bucketSize用double
class Solution {
public:
    int maximumGap(vector<int> &num) {
        if (num.size() < 2) return 0;
        int min_val = num[0];
        int max_val = num[0];
        for (int i = 1; i < num.size(); i++) {
            min_val = min(num[i],min_val);
            max_val = max(num[i],max_val);
        }
        
        double bucketSize = (max_val - min_val) * 1.0 / (num.size() - 1);
        vector<int> maxBucket(num.size() - 1, -1);
        vector<int> minBucket(num.size() - 1, INT_MAX);
        for (int i = 0; i < num.size(); i++) {
            if (num[i] == min_val || num[i] == max_val) continue;
            int bucket = (int)((num[i] - min_val) / bucketSize);
            maxBucket[bucket] = max(num[i],maxBucket[bucket]);
            minBucket[bucket] = min(num[i],minBucket[bucket]);
        }
        
        int maxGap = INT_MIN;
        int preMax = min_val;
        for (int i = 0; i < num.size() - 1; i++) {
            if (maxBucket[i] == -1) continue;
            maxGap = max(maxGap,minBucket[i] - preMax);
            preMax = maxBucket[i];
        }
        maxGap = max(maxGap,max_val - preMax);
        return maxGap;
    }
};
Update Feb-18-2015
radix sort
class Solution {
public:
    int maximumGap(vector<int> &num) {
        if (num.size() < 2) return 0;
        vector<int> one;
        vector<int> zero;
        
        for (int i = 0; i < 32; i++) {
            int mask = 1 << i;
            for (int j = 0; j < num.size(); j++) {
                if (num[j] & mask) {
                    one.push_back(num[j]);
                }else {
                    zero.push_back(num[j]);
                }
            }
            
            zero.insert(zero.end(),one.begin(),one.end());
            num =zero;
            one.clear();
            zero.clear();
        }
        
        int maxGap = 0;
        for (int i = 1; i < num.size(); i++) {
            maxGap = max(num[i] - num[i - 1],maxGap);
        }
        
        return maxGap;
    }
};
if (num[j] & mask) 判断的是0或者是非0,而不是1或0
radix sort, 10-base
REF
class Solution {
public:
    int getMax(vector<int> &nums) {
        int maxNum = 0;
        for (int i = 0; i < nums.size(); i++) {
            maxNum = max(nums[i],maxNum);
        }
        return maxNum;
    }

    void countSort(vector<int>& nums, int m) {
        vector<int> count(10,0);
        for (int i = 0; i < nums.size(); i++) {
            count[(nums[i] / m) % 10]++;
        }
        
        // calculate start point for each key
        int total = 0;
        for (int i = 0; i < 10; i++) {
            int oldCount = count[i];
            count[i] = total;
            total += oldCount;
        }
        
        // sort
        vector<int> rt(nums.size());
        for (int i = 0; i < nums.size(); i++) {
            rt[count[(nums[i] / m) % 10]] = nums[i];
            count[(nums[i] / m) % 10]++;
        }
        
        nums = rt;
    }

    int maximumGap(vector<int>& nums) {
        int maxNumber = getMax(nums);
        for (int m = 1; m <= maxNumber; m *= 10) {
            countSort(nums,m);
        }
        
        int maxGap = 0;
        for (int i = 1; i < nums.size(); i++) {
            maxGap = max(maxGap,nums[i] - nums[i - 1]);
        }
        
        return maxGap;
    }
};

Thursday, January 29, 2015

Day 97, ##, Largest Number, Compare Version Numbers

Largest Number

Given a list of non negative integers, arrange them such that they form the largest number.
For example, given [3, 30, 34, 5, 9], the largest formed number is 9534330.
Note: The result may be very large, so you need to return a string instead of an integer.
-----------------------------------
COME_BACK
class Solution {
public:
    static bool cmp(string s1,string s2) {
        return (s1 + s2) < (s2 + s1);
    }
    
    string largestNumber(vector<int> &num) {
        vector<string> strings(num.size());
        for (int i = 0; i < num.size(); i++) {
            strings[i] = to_string(num[i]);
        }
        
        sort(strings.begin(),strings.end(),cmp);
        if (strings.back() == "0") {
            return "0";
        }
        
        string rt = "";
        for (int i = strings.size() - 1; i >= 0; i--) {
            rt += strings[i]; 
        }
        
        return rt;
    }
};

Compare Version Numbers

Compare two version numbers version1 and version1.
If version1 > version2 return 1, if version1 < version2 return -1, otherwise return 0.
You may assume that the version strings are non-empty and contain only digits and the . character.
The . character does not represent a decimal point and is used to separate number sequences.
For instance, 2.5 is not "two and a half" or "half way to version three", it is the fifth second-level revision of the second first-level revision.
Here is an example of version numbers ordering:
0.1 < 1.1 < 1.2 < 13.37
----------------------------------------------------------
class Solution {
public:
    int getNextSubString(string &str, int &i) {
        int rt = 0;
        while (i < str.length() && str[i] != '.') {
            rt = rt * 10 + (str[i] - '0');
            i++;
        }
        
        i++;
        return rt;
    }

    int compareVersion(string version1, string version2) {
        int itr1 = 0, itr2 = 0;
        while (itr1 < version1.length() || itr2 < version2.length()) {
            int s1 = getNextSubString(version1,itr1);
            int s2 = getNextSubString(version2,itr2);

            if (s1 > s2) return 1;
            if (s1 < s2) return -1;
        }
        return 0;
    }
};

Wednesday, January 28, 2015

Day 96, ##, Topological Sorting

Topological Sorting 

Given an directed graph, a topological order of the graph nodes is defined as follow:
  • For each directed edge A-->B in graph, A must before B in the order list.
  • The first node in the order can be any node in the graph with no nodes direct to it.
Find any topological order for the given graph.
Note
You can assume that there is at least one topological order in the graph.
Example
For graph as follow:

The topological order can be:
[0, 1, 2, 3, 4, 5]
or
[0, 2, 3, 1, 5, 4]
or
....

Challenge
Can you do it in both BFS and DFS?
----------------------------------------------------------------------------
 DFS
/**
 * Definition for Directed graph.
 * struct DirectedGraphNode {
 *     int label;
 *     vector<DirectedGraphNode *> neighbors;
 *     DirectedGraphNode(int x) : label(x) {};
 * };
 */
class Solution {
public:
    /**
     * @param graph: A list of Directed graph node
     * @return: Any topological order for the given graph.
     */
     
    void dfs(DirectedGraphNode * node, vector<DirectedGraphNode*> &rt,unordered_set<DirectedGraphNode*> &visit) {
        visit.insert(node);
        for (int i = 0; i < node->neighbors.size(); i++) {
            if (visit.find(node->neighbors[i]) == visit.end()) {
                dfs(node->neighbors[i], rt, visit);
            }
        }
        
        rt.push_back(node);
    }
     
    vector<DirectedGraphNode*> topSort(vector<DirectedGraphNode*> graph) {
        // write your code here
        vector<DirectedGraphNode*> rt;
        unordered_set<DirectedGraphNode*> visit;
        
        for (int i = 0; i < graph.size(); i++) {
            if (visit.find(graph[i]) == visit.end()) {
                dfs(graph[i],rt,visit);
            }
        }
        
        reverse(rt.begin(),rt.end());
        return rt;
    }
};


Tuesday, January 27, 2015

Day 95, ##, Excel Sheet Column Title, Excel Sheet Column Number, Missing Ranges

Excel Sheet Column Title
Given a positive integer, return its corresponding column title as appear in an Excel sheet.
For example:
    1 -> A
    2 -> B
    3 -> C
    ...
    26 -> Z
    27 -> AA
    28 -> AB 
-----------------------------------
similar to convert a base 10 number to any base number
可以考虑1-26 为 0 - 25,进行转换
class Solution {
public:
    string convertToTitle(int n) {
        string s = "";
        
        while (n > 0) {
            char c;
            if (n % 26 == 0) {
                c = 'Z';
                n--;
            }else 
                c = n % 26 - 1 + 'A';
            n = n / 26;
            s = c + s;
        }
        
        return s;
    }
};

Excel Sheet Column Number

Related to question Excel Sheet Column Title
Given a column title as appear in an Excel sheet, return its corresponding column number.
For example:
    A -> 1
    B -> 2
    C -> 3
    ...
    Z -> 26
    AA -> 27
    AB -> 28 
----------------------------------------------------
class Solution {
public:
    int titleToNumber(string s) {
        int rt = 0;
        for (int i = 0; i < s.length(); i++) {
            int temp = s[i] - 'A' + 1;
            rt = rt * 26 + temp;
        }
        
        return rt;
    }
};

Missing Ranges

Given a sorted integer array where the range of elements are [lower, upper] inclusive, return its missing ranges.
For example, given [0, 1, 3, 50, 75], lower = 0 and upper = 99, return ["2", "4->49", "51->74", "76->99"]. ----------------------------------------------------------------------
class Solution {
public:
    vector<string> findMissingRanges(int A[], int n, int lower, int upper) {
        vector<string> rt;
        string mid = "->";
        string s = "";
        
        if (n == 0) {
            if (lower == upper) {
                rt.push_back(to_string(lower));
            }else {
                rt.push_back(to_string(lower) + mid + to_string(upper));
            }
            
            return rt;
        }
        
        if (A[0] > lower) {
            int temp = A[0] - 1;
            if (A[0] - 1 == lower) {
                s = to_string(lower);
            }else 
                s = to_string(lower) + mid + to_string(A[0] - 1);
            rt.push_back(s);
        }
        
        for (int i = 1; i < n; i++) {
            if (A[i] == A[i - 1] + 1) continue;
            string low = to_string(A[i - 1] + 1);
            string up = to_string(A[i] - 1);
            if (low == up) 
                s = low;
            else
                s = low + mid + up;
            rt.push_back(s);
        }
        
        if (A[n - 1] < upper) {
            if (A[n - 1] + 1 == upper)
                s = to_string(upper);
            else
                s = to_string(A[n - 1] + 1) + mid + to_string(upper);
            rt.push_back(s);
        }
        
        return rt;
    }
};

更新
class Solution {
public:
    vector<string> findMissingRanges(vector<int>& nums, int lower, int upper) {
        nums.insert(nums.begin(),lower - 1);
        nums.push_back(upper + 1);
        
        vector<string> rt;
        int start = 0;
        for (int i = 1; i < nums.size(); i++) {
            if (nums[i] == nums[i - 1] + 1 || nums[i] == nums[i - 1]) {
                continue;
            }else if (nums[i] - 2 == nums[i - 1]) {
                rt.push_back(to_string(nums[i] - 1));
            }else {
                rt.push_back(to_string(nums[i - 1] + 1) + "->" + to_string(nums[i] - 1));
            }
        }
        
        return rt;
    }
};

Thursday, January 22, 2015

Day 94, ##, Find Peak Element

Find Peak Element

A peak element is an element that is greater than its neighbors.
Given an input array where num[i] ≠ num[i+1], find a peak element and return its index.
The array may contain multiple peaks, in that case return the index to any one of the peaks is fine.
You may imagine that num[-1] = num[n] = -∞.
For example, in array [1, 2, 3, 1], 3 is a peak element and your function should return the index number 2.

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

class Solution {
public:
    int findPeakElement(const vector<int> &num) {
        if (num[0] > num[1]) return 0;
        if (num[num.size() - 1] > num[num.size() - 2]) return num.size() - 1; 
        
        int left = 1, right = num.size() - 2;
        while (left <= right) {
            int mid = right + (left - right) / 2;
            if (num[mid] > num[mid - 1] && num[mid] > num[mid + 1]) {
                return mid;
            }else if (num[mid] > num[mid + 1]) {
                right = mid - 1;
            }else {
                left = mid + 1;
            }
        }
        
        return num.size() - 1;
    }
};

Java, updated on Oct-10th-2018
1. left < right 保证了mid + 1时不用对mid做boundry check
2. right = mid, 因为此时[mid] > [mid + 1], mid还算是一个candidate
3. ToDo: 二分法的一种写法是不设base case,然后由while里的条件来结束,最后返回left。https://shibaili.blogspot.com/2018/10/658-find-k-closest-elements.html 第2个方法用了类似的方法

class Solution {
    public int findPeakElement(int[] nums) {
        int left = 0, right = nums.length - 1;
        
        while (left < right) {
            int mid = (left + right) / 2;
            if (nums[mid] < nums[mid + 1]) {
                left = mid + 1;
            }else {
                right = mid;
            }
        }
        
        return left;
    }
}

Wednesday, January 21, 2015

Day 93, ##, One Edit Distance

One Edit Distance

Given two strings S and T, determine if they are both one edit distance apart.
-------------------------------------------------------
edit之后可以之后对剩下的string取等式
class Solution {
public:
    bool isOneEditDistance(string s, string t) {
        int d = s.size() - t.size();
        if (abs(d) > 1 || s == t) return false; 
        
        for (int i = 0; i < s.length(); i++) {
            if (i < t.length() && s[i] != t[i]) {
                return s.substr(i + 1) == t.substr(i + 1) 
                        || s.substr(i + 1) == t.substr(i)
                        || s.substr(i) == t.substr(i + 1);
            }
        }
        
        return true;
    }
};

Sunday, January 18, 2015

Day 92, ##, Intersection of Two Linked Lists

Intersection of Two Linked Lists


Write a program to find the node at which the intersection of two singly linked lists begins.

For example, the following two linked lists:
A:          a1 → a2
                   ↘
                     c1 → c2 → c3
                   ↗            
B:     b1 → b2 → b3
begin to intersect at node c1.

Notes:
  • If the two linked lists have no intersection at all, return null.
  • The linked lists must retain their original structure after the function returns.
  • You may assume there are no cycles anywhere in the entire linked structure.
  • Your code should preferably run in O(n) time and use only O(1) memory.
Credits:
Special thanks to @stellari for adding this problem and creating all test cases.
------------------------------------------------------------
Solution #1, attach A's end to A's start. solve it as finding the start of cycle in a linked list
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if (headA == NULL) return NULL;
        ListNode *end =headA;
        while (end->next != NULL) {
            end = end->next;
        }
        end->next = headA;
        
        ListNode *fast = headB, *slow = headB;
        while (fast != NULL) {
            fast = fast->next;
            slow = slow->next;
            if (fast != NULL) {
                fast = fast->next;
            }else {
                end->next = NULL;
                return NULL;
            }
            
            if (slow == fast) break;
        }
        
        if (fast == NULL) {
            end->next = NULL;
            return NULL;
        }
        
        fast = headB;
        while (fast != slow) {
            slow = slow->next;
            fast = fast->next;
        }
        end->next = NULL;
        
        return fast;
    }
};
Solution #2
explanation https://oj.leetcode.com/problems/intersection-of-two-linked-lists/solution/
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode *endA = NULL, *endB = NULL;
        ListNode *itrA = headA, *itrB = headB;
        
        while (itrA != NULL && itrB != NULL) {
            if (endA != NULL && endB != NULL && endA != endB) return NULL;
            if (itrA == itrB) return itrA;
            
            if (itrA->next == NULL) {
                if (endA == NULL) endA = itrA;
                itrA = headB;
            }else {
                itrA = itrA->next;
            }
            
            if (itrB->next == NULL) {
                if (endB == NULL) endB = itrB;
                itrB = headA;
            }else {
                itrB = itrB->next;
            }
        }
        
        return NULL;
    }
};

Thursday, January 15, 2015

Day 91, #159 #173, Longest Substring with At Most Two Distinct Characters, Binary Search Tree Iterator


Longest Substring with At Most Two Distinct Characters


Given a string, find the length of the longest substring T that contains at most 2 distinct characters.
For example, Given s = “eceba”,
T is "ece" which its length is 3.
------------------------------------------------------
have two counters for each char, once a third char comes in, exhaust either counter, then set it to the third char
class Solution {
public:
    int lengthOfLongestSubstringTwoDistinct(string s) {
        char first = '\0', second = '\0';
        int count1 = 0, count2 = 0;
        int start = 0,longest = 0;
        for (int i = 0; i < s.length(); i++) {
            if (count1 == 0 && count2 == 0) {
                first = s[i];
                count1++;
            }else if (count2 == 0 && first != s[i]) {
                second = s[i];
                count2++;
            }else if (first == s[i]) {
                count1++;
            }else if (second == s[i]) {
                count2++;
            }else {
                while (true) {
                    if (s[start] == first) count1--;
                    else count2--;
                    start++;
                    if (count1 == 0) {
                        first = s[i];
                        count1 = 1;
                        break;
                    }
                    if (count2 == 0) {
                        second = s[i];
                        count2 = 1;
                        break;
                    }
                }
            }
            
            longest = max(longest,i - start + 1);
        }
        
        return longest;
    }
};

网上看到的,i, j 记录2个不同char的最新位置
int lengthOfLongestSubstringTwoDistinct(string s) {
        int i = 0, j = -1;
        int maxLen = 0;
        for (int k = 1; k < s.size(); k++) {
            if (s[k] == s[k-1]) continue;
            if (j > -1 && s[k] != s[j]) {
                maxLen = max(maxLen, k - i);
                i = j + 1;
            }
            j = k - 1;
        }
        return maxLen > (s.size() - i) ? maxLen : s.size() - i;
    }

更新
class Solution {
public:
    int lengthOfLongestSubstringTwoDistinct(string s) {
        unordered_map<char,int> dic;
        int start = 0, longest = 0;
        
        for (int i = 0; i < s.length(); i++) {
            if (dic.find(s[i]) != dic.end()) {
                dic[s[i]]++;
            }else {
                dic[s[i]] = 1;
            }
            while (dic.size() > 2) {
                dic[s[start]]--;
                if (dic[s[start]] == 0) {
                    dic.erase(s[start]);
                }
                start++;
            }
            longest = max(longest,i - start + 1);
        }
        
        return longest;
    }
};


Binary Search Tree Iterator


Implement an iterator over a binary search tree (BST). Your iterator will be initialized with the root node of a BST.
Calling next() will return the next smallest number in the BST.
Note: next() and hasNext() should run in average O(1) time and uses O(h) memory, where h is the height of the tree.
Credits:
Special thanks to @ts for adding this problem and creating all test cases. ----------------------------------------------------------------
/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class BSTIterator {
public:
    BSTIterator(TreeNode *root) {
        TreeNode *p = root;
        
        while (p != NULL) {
            st.push(p);
            p = p->left;
        }
        
    }

    /** @return whether we have a next smallest number */
    bool hasNext() {
        return st.size() > 0;
    }

    /** @return the next smallest number */
    int next() {
        if (st.empty()) throw exception();
        TreeNode *rt = st.top();
        TreeNode *p = rt->right;
        st.pop();
        
        while (p != NULL) {
            st.push(p);
            p = p->left;
        }
        
        return rt->val;
    }
private: 
    stack<TreeNode *> st;
};

/**
 * Your BSTIterator will be called like this:
 * BSTIterator i = BSTIterator(root);
 * while (i.hasNext()) cout << i.next();
 */

Another implementation
/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class BSTIterator {
public:
    BSTIterator(TreeNode *root) {
        current = root;
    }

    /** @return whether we have a next smallest number */
    bool hasNext() {
        return !st.empty() || current != NULL;
    }

    /** @return the next smallest number */
    int next() {
        while (current != NULL) {
            st.push(current);
            current = current->left;
        }
        
        current = st.top();
        st.pop();
        int rt = current->val;
        current = current->right;
        return rt;
    }
private:
    stack<TreeNode*> st;
    TreeNode *current;
};

/**
 * Your BSTIterator will be called like this:
 * BSTIterator i = BSTIterator(root);
 * while (i.hasNext()) cout << i.next();
 */

更新
/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class BSTIterator {
public:
    BSTIterator(TreeNode *root) {
        this->root = root;
    }

    /** @return whether we have a next smallest number */
    bool hasNext() {
        return !st.empty() || root != NULL;
    }

    /** @return the next smallest number */
    int next() {
        while (!st.empty() || root) {
            if (root != NULL) {
                st.push(root);
                root = root->left;
            }else {
                TreeNode *rt = st.top();
                st.pop();
                root = rt->right;
                return rt->val;
            }
        }
    }
private:
    stack<TreeNode *> st;
    TreeNode *root;
};

/**
 * Your BSTIterator will be called like this:
 * BSTIterator i = BSTIterator(root);
 * while (i.hasNext()) cout << i.next();
 */

Java, Jun-14-2018
/**
 * Definition for binary tree
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */

public class BSTIterator {
    
    private Stack st;

    public BSTIterator(TreeNode root) {
        st = new Stack<>();
        pushToStack(root);
    }

    /** @return whether we have a next smallest number */
    public boolean hasNext() {
        return !st.isEmpty();
    }

    /** @return the next smallest number */
    public int next() {
        TreeNode cur = st.pop();
        pushToStack(cur.right);
        
        return cur.val;
    }
    
    private void pushToStack(TreeNode root) {
        while (root != null) {
            st.push(root);
            root = root.left;
        }
    }
}

/**
 * Your BSTIterator will be called like this:
 * BSTIterator i = new BSTIterator(root);
 * while (i.hasNext()) v[f()] = i.next();
 */

Wednesday, January 14, 2015

Graphs

DFS:
graph cycle detection:
detect cycle in a directed graph
have a hash set for current visited nodes, in recursion stack
http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm

detect cycle in a undirected graph
as long as a node is found visited already and it's not the parent of the current node, then there's a cycle

----------------------------------------------------------
DAG, shortest path algorithms

#1
 topological sort the graph, one pass to find the start node and update shortest path to each node

----------------------------------------
Bellmen-Ford
correctness: relax one edge into final stage at each outer iteration

Numerics

Numerics
large number addition







large number multiply