Sunday, April 28, 2013

Day 23, 121, Best Time to Buy and Sell Stock

Best Time to Buy and Sell Stock
Say you have an array for which the ith element is the price of a given stock on day i.
If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit.
-------------------------------------------------
 Solution #1 O(n^2) straight forward iteration.
class Solution {
public:

    void profit (vector<int> &prices, vector<int> &prf, int index) {
        int cur = prices[index];
        int max = 0;
        for (int i=index+1;i<prices.size();i++) {
            int dif = prices[i] - cur;
            if (dif > max) {
                max = dif;
            }
        }
        prf[index] = max;
        if (index + 1 < prices.size())
            profit(prices,prf,index+1);
        
    }
    
    int findMax (vector<int> &prf) {
        int max = 0;
        for (int i=0;i<prf.size();i++) {
            if (prf[i]>max) max = prf[i]; 
        }
        return max;
    }

    int maxProfit(vector<int> &prices) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if (prices.size() == 0) return 0;
        vector<int> prf(prices.size());
        profit(prices,prf,0);
        return findMax(prf);
    }
};

Solution #2 O(n)
Note: tracking the index of minimum value

class Solution {
public:
    int maxProfit(vector<int> &prices) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        int buy=0,sell=0;
        int min=0;
        int maxDif = 0;
        for (int i=0;i<prices.size();i++) {
            if (prices[min] > prices[i]) {
                min = i;    
            }
            int dif = prices[i] - prices[min];
            if (dif > maxDif) {
                buy = min;
                sell = i;
                maxDif = dif; 
            } 
        }
        return maxDif;
    }
};
Solution #3  O(n) space and efficiency
 DP: max = prices[i] - prices[i-1] + prices[i-1] - prices[i-2] + .... + prices[j+1] - prices[j] = prices[i]- prices[j]
class Solution {
public:
    int maxProfit(vector<int> &prices) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        int size = prices.size();
        if (size < 2) {
            return 0;
        }
        int max = 0;
        int curMax = 0;
        for (int i=1;i<size;i++) {
            if (curMax > 0) {
                curMax += prices[i] - prices[i-1];
            }else {
                curMax = prices[i] - prices[i-1];
            }
            if (curMax > max) {
                max = curMax;
            }
        }
        return max;
    }
};
Update - 1, Dec 27th 2013
Solution #4, a much easier DP approach 
dp[i] represents the maximum profit among all prices, starting at index 0 to i. Hence dp[prices.size() - 1] has the max value we are looking for.
class Solution {
public:
    int maxProfit(vector<int> &prices) {
        if (prices.size() == 0) return 0;
        vector<int> dp(prices.size(),0);
        int minimum = prices[0];
        for (int i = 1; i < prices.size(); i++) {
            dp[i] = max(dp[i - 1], prices[i] - minimum);
            minimum = mim(prices[i],minimum);
        }
        return dp[prices.size() - 1];
    }
};
Update - 2, Mar 29th 2014
Optimized space of Solution #4
class Solution {
public:
    int maxProfit(vector<int> &prices) {
        int size = prices.size();
        if (size == 0) {
            return 0;
        }    
        
        int minimum = prices[0];
        int maxP = 0;
        for (int i = 0; i < size; i++) {
            maxP = max (maxP, prices[i] - minimum);
            minimum = min(minimum,prices[i]);
        }
        
        return maxP;
    }
};
Solution #5, similar to #4. DP. thanks to Lan Xu
dp[i] has the highest price from dp[i + 1] to end
class Solution {
public:
    int maxProfit(vector<int> &prices) {
        int size = prices.size();
        if (size == 0) {
            return 0;
        }    
        
        vector<int> dp(size,0);
        for (int i = size - 2; i >= 0; i--) {
            dp[i] = max(dp[i + 1], prices[i + 1]);
        }
        
        int maxP = 0;
        for (int i = 0; i < size; i++) {
            maxP = max(maxP, dp[i] - prices[i]);
        }
        
        return maxP;
    }
};
Optimized space
class Solution {
public:
    int maxProfit(vector<int> &prices) {
        int size = prices.size();
        if (size == 0) {
            return 0;
        }    
        
        int maxP = 0;
        int highest = prices[size - 1]; // highest value from i to end
        for (int i = size - 2; i >= 0; i--) {
            maxP = max(maxP, highest - prices[i]);
            highest = max(highest, prices[i]);
        }
  
        return maxP;
    }
};

Thursday, April 25, 2013

Day 22, 118, 119 Pascal's Triangle, Pascal's Triangle II

Pascal's Triangle
Given numRows, generate the first numRows of Pascal's triangle.
For example, given numRows = 5,
Return
[
     [1],
    [1,1],
   [1,2,1],
  [1,3,3,1],
 [1,4,6,4,1]
] 
------------------------------
Note that 
1) vector<vector<int> > ret(size)
    is not working
2) "vector<int> v;
      v[0] = val;"
      is not working,    
      has to be
     "vector<int> v(size);
      v[0] = val or v.push_back(val)"  
class Solution {
public:
    vector<vector<int>> generate(int numRows) {
        vector<vector<int>> rt(numRows,vector<int>());
        for (int row = 0; row < numRows; row++) {
            for (int i = 0; i <= row; i++) {
                if (i == 0 || i == row) {
                    rt[row].push_back(1);
                }else {
                    rt[row].push_back(rt[row - 1][i - 1] + rt[row - 1][i]);
                }
            }
        }
        
        return rt;
    }
};
Pascal's Triangle II
Given an index k, return the kth row of the Pascal's triangle.
For example, given k = 3,
Return [1,3,3,1].
Note:
Could you optimize your algorithm to use only O(k) extra space?
-----------------------------------------------
Solution #1, O(k) space, v is symmetrical
other possible solution: start calculating at the end of each row

class Solution {
public:
        vector<int> getRow(int rowIndex) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        rowIndex++;
        vector<int> v(rowIndex);
        v[0]=1;
        if (rowIndex == 1) {
            return v;
        }
        int k=2;
        while (k <= rowIndex) {
            if (k%2 == 0) {
                for (int i=0;i<k/2;i++) {
                    v[i] = v[k-1-i] + v[k-2-i];
                }
                for (int i=k/2;i<k;i++) {
                    v[i] = v[k-1-i];
                }
            }else {
                int mid = v[k/2] * 2;
                for (int i=1;i<k/2;i++) {
                    v[i] = v[k-1-i] + v[k-2-i];
                }
                for (int i=k/2+1;i<k;i++) {
                    v[i] = v[k-1-i];
                }
                v[k/2] = mid;
            }
            k++;
        }
        return v;
    }
};
Update on Sep-09-2014
Solution #2, Binomial theorem
long long casting to prevent from overflow
COME_BACK
class Solution {
public:
    vector<int> getRow(int rowIndex) {
        vector<int> rt(rowIndex + 1);
        rt[0] = 1;
        rt[rowIndex] = 1;
        
        for (int i = 1; i < rowIndex; i++) {
            rt[i] = (long long)rt[i - 1] * (rowIndex - i + 1) / i;
        }
        
        return rt;
    }
};
Update on Feb-15-2015

class Solution {
public:
    vector<int> getRow(int rowIndex) {
        vector<int> rt(rowIndex + 1,0);
        rt[0] = 1;
        for (int i = 1; i <= rowIndex; i++) {
            for (int j = i; j > 0; j--) {
                rt[j] = rt[j] + rt[j - 1];
            }
        }
        
        return rt;
    }
};

Tuesday, April 23, 2013

Day 21, 113, Path Sum II

Path Sum II
Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum.
For example:
Given the below binary tree and sum = 22,
              5
             / \
            4   8
           /   / \
          11  13  4
         /  \    / \
        7    2  5   1
return
[
   [5,4,11,2],
   [5,8,4,5]
] 
---------- 
based on Path Sum
/**
 * 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 ps (TreeNode *root, int sum, int curSum, vector<int> curV, vector<vector<int> > &re) {
        if (root != NULL) {
            curSum += root->val;
            curV.push_back(root->val);
            if (root->left == NULL && root->right == NULL) {
                if (curSum == sum) {
                    re.push_back(curV);
                }
            }else {
                ps(root->left,sum,curSum,curV,re);
                ps(root->right,sum,curSum,curV,re);
            }
        }
    }

    vector<vector<int> > pathSum(TreeNode *root, int sum) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        vector<int> path;
        vector<vector<int> > paths;
        ps(root,sum,0,path,paths);
        return paths;
    }
};

优化了下用于暂时储存的vector,此法可用于若干种类似题目
/**
 * 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 helper(TreeNode *root,int sum, vector<vector<int> > &rt, vector<int> &cur) {
        if (root == NULL) return;
        if (root->val == sum && root->left == NULL && root->right == NULL) {
            vector<int> t = cur;
            t.push_back(root->val);
            rt.push_back(t);
            return;
        }
        
        cur.push_back(root->val);
        helper(root->left,sum - root->val,rt,cur);
        helper(root->right,sum - root->val,rt,cur);
        cur.pop_back();
    }

    vector<vector<int>> pathSum(TreeNode* root, int sum) {
        vector<vector<int> > rt;
        vector<int> cur;
        
        helper(root,sum,rt,cur);
        return rt;
    }
};

Saturday, April 20, 2013

Day 20, 88,108, Merge Sorted Array, Convert Sorted Array to Binary Search Tree

Sorted Array
Given two sorted integer arrays A and B, merge B into A as one sorted array.
Note:
You may assume that A has enough space to hold additional elements from B. The number of elements initialized in A and B are m and n respectively.
-------------------------------------
 Solution #1, pooooooooooooooor algorithm, O(m*n)?
class Solution {
public:
    void move (int i, int A[], int m) {
        for (int j=m;j>=i;j--) {
            A[j+1] = A[j];
        }
    }
    
    void merge(int A[], int m, int B[], int n) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        
        int j=0;
        for (int i=0;i<m;i++) {
            if (j<n && A[i] > B[j]) {
                move(i,A,m);
                m++;
                A[i] = B[j];
                j++;
            }
        }
        if (j<n) {
            int length = n-j;
            for (int i=m;i<m+length+1;i++) {
                A[i] = B[j];
                j++;
            }
        }
    }
};
Solution #2, start from the back of two arrays
O(m+n)complexity, no extra space used
class Solution {
public:
    void merge(int A[], int m, int B[], int n) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        int index = m+n-1;
        int a = m-1;
        int b = n-1;
        for (;index >= 0;index--) {
            if (a>=0 && b>=0 && A[a] > B[b]) {
                A[index] = A[a];
                a--;
            }else if (b>=0) {
                A[index] = B[b];
                b--;
            }
        }
    }
};
Convert Sorted Array to Binary Search Tree
Given an array where elements are sorted in ascending order, convert it to a height balanced BST.
------------------------------
recursion, nothing fancy
/**
 * 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 *devide (int left, int right, vector<int> &num) {
        int mid = (left+right) / 2;
        TreeNode* root = new TreeNode(num[mid]);
        if (left <= mid-1 )
            root->left = devide(left,mid-1,num); 
        if (right >= mid+1)
            root->right = devide(mid+1,right,num); 
        return root;
    }

    TreeNode *sortedArrayToBST(vector<int> &num) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if (num.size() == 0) return NULL;
        return devide(0,num.size()-1,num);
    }
};
Update on Sep-05-2014
Set up the conditions so one node does not contain itself as its child

Friday, April 19, 2013

Day 19, 70,80 Climbing Stairs, Remove Duplicates from Sorted Array II

Climbing Stairs
You are climbing a stair case. It takes n steps to reach to the top.
Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?
------------------------------
-- Fibonacci number --
Solution #1 straight forward recursion

class Solution {
public:
    int climbStairs(int n) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if (n == 0) {
            return 1;
        }
        if (n < 0) {
            return 0;   
        }
        return climbStairs(n-1) + climbStairs(n-2);        
    }
};
Solution #2 DP, memoization
class Solution {
public:
    
    int climb (int n,int ma[]) {
        if (n == 0) {
            return 1;
        }
        if (ma[n-1] == -1) {
            ma[n-1] = climb(n-1,ma);
        }
        if (n == 1) {   // eliminate n-2
            return ma[n-1];
        }
        if (ma[n-2] == -1) {
            ma[n-2] == climb(n-2,ma);
        }
        return ma[n-1] + ma[n-2]; 
    }


    int climbStairs(int n) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        int ma[n+2];
        for (int i=0;i<n+2;i++) {
            ma[i] = -1;
        }
        return climb(n,ma);
    }
};
Solution #3 DP, bottom u (can be optimized to O(1) space by using int a[3])
class Solution {
public:

    int climbStairs(int n) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        int ma[n+1];
        ma[n] = 1;
        ma[n-1] = 1;
        for (int i=n;i>1;i--) {
            ma[i-2] = ma[i] + ma[i-1];
        }
        return ma[0]; 
    }
};
Remove Duplicates from Sorted Array II 
Follow up for "Remove Duplicates":
What if duplicates are allowed at most twice?
For example,
Given sorted array A = [1,1,1,2,2,3],
Your function should return length = 5, and A is now [1,1,2,2,3].
-----------------
Similar to  Remove Duplicates from Sorted Array
add a flag to track the first duplicate
class Solution {
public:
    int removeDuplicates(int A[], int n) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if (n == 0) {
            return 0;
        } 
        bool flag = false;  // duplicates are allowed at most twice
        int start = 0;
        for (int i=1;i<n;i++) {
            if (A[start] == A[i]) {
                if (!flag) {    // found first duplicate
                    start++;
                    A[start] = A[i];
                    flag = true;
                }
            }else {
                start++;
                A[start] = A[i];
                flag = false;
            }
            
        }
        return start + 1;
    }
};
Update on Sep-05-2014
This can handle arbitrary number of dups
class Solution {
public:
    int removeDuplicates(int A[], int n) {
        if (n == 0) return n;
        int count = 1;
        int indexOfLastElement = 0;
        
        for (int i = 1; i < n; i++) {
            if (A[indexOfLastElement] == A[i]) {
                if (count < 2) {
                    indexOfLastElement++;    
                    A[indexOfLastElement] = A[i]; // watch out for this line
                    count++;
                }
            }else {
                indexOfLastElement++;
                A[indexOfLastElement] = A[i];
                count = 1;
            }
        }
        
        return indexOfLastElement + 1;
    }
};

Thursday, April 18, 2013

Day 18, 67 Add Binary

Add Binary
Given two binary strings, return their sum (also a binary string).
For example,
a = "11"
b = "1"
Return "100".
-------------------
Solution #1, Straight forward
class Solution {
public:
    string addBinary(string a, string b) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        int pre = 0, length = 0;
        string lon,sht;
        // find the longer string
        if (a.length() > b.length()) {
            length = a.length();
            lon = a;
            sht = b;
        }else {
            length = b.length();
            lon = b;
            sht = a;
        }
        for (int i=length-1;i>=0;i--) {
            if (sht.length() >= length - i) {
                if (sht[sht.length() - length + i] == '1' && lon[i] == '1') { // 1 + 1
                    if (pre == 0) {
                        lon[i] = '0';
                        pre = 1;
                    }
                }else if (sht[sht.length() - length + i] == '0' && lon[i] == '0') { // 0 + 0
                    if (pre == 1) {
                        lon[i] = '1';
                        pre = 0;
                    }
                }else if (pre == 1) { // '0'+'1'
                    lon[i] = '0';
                    pre = 1;
                }else {
                    lon[i] = '1';
                }
            }else { // short string ends, long string continues 
                if (pre == 1) {
                    if (lon[i] == '1') {
                        lon[i] = '0';
                    }else {
                        lon[i] = '1';
                        pre = 0;
                    }
                }
            }
        }
        if (pre == 1) { // one more digit
            lon = '1' + lon;
        }
        return lon;
    }
};
Update on Jul-10-2015
Solution #2, 加法时转化为integer
class Solution {
public:
    string addBinary(string a, string b) {
        int m = a.length(), n = b.length();
        int len = max(m,n);
        int carry = 0;
        string s = "";
        
        for (int i = 0; i < len; i++) {
            if (i < m) {
                carry += a[m - 1 - i] - '0';
            }
            if (i < n) {
                carry += b[n - 1 - i] - '0';
            }
            
            char sum = carry % 2 + '0';
            s = sum + s;
            carry = carry / 2;
        }
        
        if (carry) s = '1' + s;
        return s;
    }
};

Day 17, 65,Valid Number

Valid Number
Validate if a given string is numeric.
Some examples:
"0" => true
" 0.1 " => true
"abc" => false
"1 a" => false
"2e10" => true
Note: It is intended for the problem statement to be ambiguous. You should gather all requirements up front before implementing one.
--------------------------------------
 from others
-- REFERENCE click me --

bool isNumber(const char *s) {
    enum InputType {
        INVALID,    // 0
        SPACE,      // 1
        SIGN,       // 2
        DIGIT,      // 3
        DOT,        // 4
        EXPONENT,   // 5
        NUM_INPUTS  // 6
    };
    int transitionTable[][NUM_INPUTS] = {
        -1,  0,  3,  1,  2, -1,     // next states for state 0
        -1,  8, -1,  1,  4,  5,     // next states for state 1
        -1, -1, -1,  4, -1, -1,     // next states for state 2
        -1, -1, -1,  1,  2, -1,     // next states for state 3
        -1,  8, -1,  4, -1,  5,     // next states for state 4
        -1, -1,  6,  7, -1, -1,     // next states for state 5
        -1, -1, -1,  7, -1, -1,     // next states for state 6
        -1,  8, -1,  7, -1, -1,     // next states for state 7
        -1,  8, -1, -1, -1, -1,     // next states for state 8
    };


int state = 0;
while (*s != '\0') {
    InputType inputType = INVALID;
    if (isspace(*s))
        inputType = SPACE;
    else if (*s == '+' || *s == '-')
        inputType = SIGN;
    else if (isdigit(*s))
        inputType = DIGIT;
    else if (*s == '.')
        inputType = DOT;
    else if (*s == 'e' || *s == 'E')
        inputType = EXPONENT;

    // Get next state from current state and input symbol
    state = transitionTable[state][inputType];

    // Invalid input
    if (state == -1) return false;
    else ++s;
}
// If the current state belongs to one of the accepting (final) states,
// then the number is valid
return state == 1 || state == 4 || state == 7 || state == 8;
}

Tuesday, April 16, 2013

Day 16, 62 Unique Path

Unique Path
A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below).
The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below).
How many possible unique paths are there?
-------------
-- REFERENCE click me --
Solution #1 straight forward. each step has two ways until passes borders or hit the finish

class Solution {
public:

    int backtrack (int x, int y, int m, int n) {
        if (x == m && y == n) {
            return 1;
        }
        if (x>m || y>n) {
            return 0;
        }
        return backtrack(x+1,y,m,n) + backtrack(x,y+1,m,n);
    }

    int uniquePaths(int m, int n) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        return backtrack(1,1,m,n);
    }
};

Solution #1 DP, memoization

class Solution {
public:
    int backtrack (int x, int y, int m, int n,int ma[][102]) {
        if (x == m && y == n) {
            return 1;
        }
        if (x>m || y>n) {
            return 0;
        }
        
        if (ma[x+1][y] == -1) {
            ma[x+1][y] = backtrack(x+1,y,m,n,ma);
        }
        if(ma[x][y+1] == -1) {
            ma[x][y+1] = backtrack(x,y+1,m,n,ma);
        }
        return ma[x+1][y] + ma[x][y+1];
    }

    int uniquePaths(int m, int n) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        int ma[102][102];
        for (int i=0;i<102;i++) {
            for (int j=0;j<102;j++) {
                ma[i][j] = -1;
            }
        }
        return backtrack(1,1,m,n,ma);
    }
};
Solution #3, DP bottom up
class Solution {
public:
    int uniquePaths(int m, int n) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        int ma[102][102] = {0};
        ma[m+1][n] = 1; // set either [m][n+1] or [m+1][n] to 1
        for (int i=m;i>0;i--) {
            for (int j=n;j>0;j--) {
                ma[i][j] = ma[i+1][j] + ma[i][j+1];
            }
        }
        return ma[1][1];
    }
};

O(n) space
class Solution {
public:
    int uniquePaths(int m, int n) {
        vector<int> dp(n,0);
        dp[n - 1] = 1;
        
        for (int i = m - 1; i >= 0; i--) {
            for (int j = n - 2; j >= 0; j--) {
                dp[j] = dp[j] + dp[j + 1];
            }
        }
        return dp[0];
    }
};

Solution #4 combinatorics
C(m+n-2, n-1)
OJ会overflow
class Solution {
public:
    int comb(int n) {
        int rt = 1;
        for (int i = 1; i <= n; i++) {
            rt *= i;
        }
        return rt;
    }

    int uniquePaths(int m, int n) {
        return comb(m + n - 2) / comb(n - 1) / comb(m - 1);
    }
};

Saturday, April 13, 2013

Day 15, 38 Count and Say

Count and Say
The count-and-say sequence is the sequence of integers beginning as follows:
1, 11, 21, 1211, 111221, ...
1 is read off as "one 1" or 11.
11 is read off as "two 1s" or 21.
21 is read off as "one 2, then one 1" or 1211.

Given an integer n, generate the nth sequence.
Note: The sequence of integers will be represented as a string.
-------------------------------------------
Solution #1 recursive

class Solution {
public:
    string countAndSay(int n) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if (n == 1) {
            return "1";
        }
        string str = countAndSay(n-1);
        int count=1;
        char c = str[0];
        string re="";
        for (int i=1;i<str.length();i++) {
            
            if (c == str[i]) {
                count++;
            }else {
                re += count + '0';
                re += c;
                c = str[i];
                count = 1;
            }            
        }
        if (count == 1) {
            // last digit, single out
            re.push_back('1');
            re.push_back(c);
        }else {
            // multi 
            re += count + '0';
            re += str.back();
        }
        return re;
    }
};

Update on Sep-04-2014
Solution #2 iterative, watch out for string and character concatenation
class Solution {
public:
    string countAndSay(int n) {
        string str = "1";
        
        for (int i = 1; i < n; i++) {
            string temp = "";
            int count = 0;
            int slow = 0;
            for (int j = 0; j < str.length(); j++) {
                if (str[slow] == str[j]) {
                    count++;
                }else {
                    char ch = count + '0';
                    temp += ch;
                    temp += str[slow];
                    count = 1;
                    slow = j;
                }
            }
            char c = count + '0';
            temp += c;
            temp += str[slow];
            str = temp;
        }
        return str;
    }
};
Solution #3, refactored recursive
class Solution {
public:
    string countAndSay(int n) {
        if (n == 1) {
            return "1";
        }
        string str = countAndSay(n - 1);
        string temp = "";
        int slow = 0;
        int count = 0;
        for (int j = 0; j < str.length(); j++) {
                if (str[slow] == str[j]) {
                    count++;
                }else {
                    char ch = count + '0';
                    temp += ch;
                    temp += str[slow];
                    count = 1;
                    slow = j;
                }
        }
        char c = count + '0';
        temp += c;
        temp += str[slow];
        
        return temp; 
    }
};

Friday, April 12, 2013

Day 14, 36 Valid Sudoku

Valid Sudoku
Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules.
The Sudoku board could be partially filled, where empty cells are filled with the character '.'.
 A partially filled sudoku which is valid.
------------------------------
Only to check if all numbers in each row, column and subset are unique, this is not a Sudoku solver
Soltuion #1, check rows, columns and subsetction
notice that vector<bool> is a special container
vector declaration

class Solution {
public:
    
    // set an array of flags
    vector<int> init() {
        vector<int> flags(10);
        for (int i=0;i<9;i++) {
            flags[i] = 0;
        }
        return flags;
    }

    bool checkRowCol(vector<vector<char> > &board) {
        for (int i=0;i<9;i++) {
            vector<int> flags = init();
            vector<int> flags2 = init();
            for (int j=0;j<9;j++) {
                int m = board[i][j] - '0';
                int n = board[j][i] - '0';
                if (board[i][j] != '.') {
                    if (flags[m] == 1) {
                        return false;
                    }
                    flags[m] = 1;
                }
                if (board[j][i] != '.') {
                    if (flags2[n] == 1) {
                        return false;
                    }
                    flags2[n] = 1;
                }
            }
        }    
        return true;
    }
    
    bool checkSub (int row, int col, vector<vector<char> > &board) {
        vector<int> flags = init();
        for (int i=0;i<3;i++) {
            for (int j=0;j<3;j++) {
                char c = board[row+i][col+j];
                int tar = c - '0';
                if (c != '.') {
                    if (flags[tar] == 1) {
                        return false;
                    }
                    flags[tar] = 1;
                }
            }
        }
        return true;
    }
    
    bool checkAllSubs (vector<vector<char> > &board) {
        
        for (int i=0;i<3;i++) {
            for (int j=0;j<3;j++) {
                if (!checkSub(3*i,j*3,board)) {
                    return false;
                }
            }
        }
        return true;
    }
    
    bool isValidSudoku(vector<vector<char> > &board) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        return checkAllSubs(board) && checkRowCol(board);

    }
};
Solution #2, from others
three 2d-arrays corresponds to row, col, subset for every cell in board[][]

class Solution {
public:
    bool isValidSudoku(vector<vector<char> > &board) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        vector<vector<bool> > rows(9, vector<bool>(9, false));
        vector<vector<bool> > cols(9, vector<bool>(9, false));
        vector<vector<bool> > blocks(9, vector<bool>(9, false));

        for (int i = 0; i < 9; ++i) {
            for (int j = 0; j < 9; ++j) {
                if (board[i][j] == '.') continue;
                int c = board[i][j] - '1'; 
                if (rows[i][c] || cols[j][c] || blocks[i - i % 3 + j / 3][c])
                    return false;
                rows[i][c] = cols[j][c] = blocks[i - i % 3 + j / 3][c] = true;
            }
        }
        return true;
    }
};

Update on Sep-04-2014
watch out for 
#1 int c = board[i][j] - '1';
#2 i - i % 3 + j / 3

In Java, updated on Feb-12th-2019
有意思的解法: https://leetcode.com/problems/valid-sudoku/discuss/15472/Short+Simple-Java-using-Strings
class Solution {
    public boolean isValidSudoku(char[][] board) {
        Set<String> set = new HashSet<>();
        
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {
                String c = "" + board[i][j];
                if (c.equals(".")) continue;
                String row = c + " row " + i;
                String col = c + " col " + j;
                String sub = c + " sub " + i / 3 * 3 + j / 3;
                
                if (set.contains(row) 
                    || set.contains(col)
                    || set.contains(sub)) return false;
                
                set.add(row);
                set.add(col);
                set.add(sub);
            }
        }
        
        return true;
    }
}

Tuesday, April 9, 2013

Day 13, 24, 35 Swap Nodes in Pairs, Search Insert Position

Swap Nodes in Pairs
Given a linked list, swap every two adjacent nodes and return its head.
For example,
Given 1->2->3->4, you should return the list as 2->1->4->3.
Your algorithm should use only constant space. You may not modify the values in the list, only nodes itself can be changed.
--------
Solution #1
pre has the address of "next" of the previous node
pre can be replace by a ListNode* type.

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *swapPairs(ListNode *head) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        ListNode *saved;
        ListNode **pre;
        if (head != NULL && head->next != NULL) {
            saved = head->next;
            pre = &(head->next);
        }else {
            return head;
        }
        while (head != NULL && head->next != NULL) {
            *pre = head->next;
            ListNode *temp = head->next->next;
            head->next->next = head;
            head->next = temp;
            pre = &(head->next);
            head = temp;
            
        }
        return saved;
    }
};

Update on Sep-03-2014 
Solution #2, with dummy node
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *swapPairs(ListNode *head) {
        ListNode *dummy;
        dummy->next = head;
        ListNode *itr = dummy;
        
        while (head != NULL && head->next != NULL) {
                itr->next = head->next;
                ListNode *temp = head->next->next;
                head->next = temp;
                itr->next->next = head;
                itr = head;
                head = temp;
        }
        
        return dummy->next;
    }
};

Search Insert Position
Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.
You may assume no duplicates in the array.
Here are few examples.
[1,3,5,6], 5 → 2
[1,3,5,6], 2 → 1
[1,3,5,6], 7 → 4
[1,3,5,6], 0 → 0
 -----------------------------------
 For #2, #3, if match is not found, compare target with A[start] to determine the final position

Solution #1 O(n) 
class Solution {
public:
    int searchInsert(int A[], int n, int target) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        
        for(int i=0;i<n;i++) {
            if (A[i] >= target) {
                return i;
            }
        }
        return n;
        
    }
};
Solution #2 O(log n), recursive
class Solution {
public:
    int rec (int A[], int start, int end, int target) {
        
        if (start >= end) {
            if (A[start] >= target) {
                return start;
            }
            return start+1;
        }
        int mid = (start + end) / 2;
        if (A[mid] == target) {
            return mid;
        }
        if (A[mid] < target) {
            return rec(A,mid+1,end,target);
        }else {
            return rec(A,start,mid-1,target);
        }
    }
    int searchInsert(int A[], int n, int target) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        
        return rec(A,0,n-1,target);
    }
};
Solution #3 O(log n)
class Solution {
public:
    int searchInsert(int A[], int n, int target) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        int start = 0, end = n-1;
        
        while (start < end) {
            int mid = (start + end) / 2;
            if (A[mid] == target) {
                return mid;
            }
            if (A[mid] < target) {
                start = mid + 1;
            }else {
                end = mid - 1;
            }
        }
        if (A[start] >= target) {
            return start;
        }else {
            return start+1;
        }
    }
};
another version
class Solution {
public:
    int searchInsert(int A[], int n, int target) {
        int mid = n / 2;
        int left = 0, right = n - 1;
        
        while (left <= right) {
            mid = (left + right) / 2;
            if (A[mid] == target) {
                return mid;
            }
            if (A[mid] > target) {
                right = mid - 1;
            }else {
                left = mid + 1;
            }
        }
        
        return right + 1;
    }
};

Monday, April 8, 2013

Day 12, 21 Merge Two Sorted Lists

Merge Two Sorted Lists
Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.
 ---------------------------------
Solution #1
handle 2 special cases at the beginning,
1) either l1 or l2 is NULL, or both are NULL
2) either l1 or l2 has only one element, or both have only one element

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *mergeTwoLists(ListNode *l1, ListNode *l2) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if (l1 == NULL) {
            return l2;
        }
        if (l2 == NULL) {
            return l1;
        }
        
        ListNode *saved, *pre;
        if (l1->val < l2->val) {
            saved = l1;
            pre = l1;
            l1 = l1->next;
            pre->next = l2;
        }else {
            saved = l2;
            pre = l2;
            l2 = l2->next;
            pre->next = l1;
        }
        
        while (l1 != NULL && l2 != NULL) {
            if (l1->val < l2->val) {
                pre->next = l1;
                pre = l1;
                l1 = l1->next;
                pre->next = l2;
            }else {
                pre->next = l2;
                pre = l2;
                l2 = l2->next;
                pre->next = l1;
            }
        }
        return saved;
    }
};

Solution #2
recursion
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *mergeTwoLists(ListNode *l1, ListNode *l2) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if (l1 == NULL) {
            return l2;
        }
        if (l2 == NULL) {
            return l1;
        }
        ListNode *re;
        if (l1->val < l2->val) {
            re = l1;
            re->next = mergeTwoLists(l1->next,l2);
        }else {
            re = l2;
            re->next = mergeTwoLists(l1,l2->next);
        }
        return re;
    }
};

Solution #3, from others
cur saves the address of the "next" in last node
class Solution {  
public:  
    ListNode *mergeTwoLists(ListNode *l1, ListNode *l2) {  
        ListNode* ret = NULL;  
        ListNode** cur = &ret;  
        while(NULL != l1 && NULL != l2)  
        {  
            if(l1->val < l2->val)  
            {  
                *cur = l1;  
                cur = &(l1->next);  
                l1 = l1->next;  
            }  
            else  
            {  
                *cur = l2;  
                cur = &(l2->next);  
                l2 = l2->next;  
            }  
        }  
        *cur = NULL == l1? l2: l1;  
        return ret;  
    }  
};  

update
Solution #4, using dummy head
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *mergeTwoLists(ListNode *l1, ListNode *l2) {
        ListNode* dummy = new ListNode(0);
        ListNode* itr = dummy;
        while (l1 != NULL && l2 != NULL) {
            if (l1->val < l2->val) {
                itr->next = l1;
                itr = l1;
                l1 = l1->next;
            }else {
                itr->next = l2;
                itr = l2;
                l2 = l2->next;
            }
        }
        if (l1 == NULL) {
            itr->next = l2;
        }else {
            itr->next = l1;
        }
        return dummy->next;
    }
};

Friday, April 5, 2013

Day 11, 14,19,20, Longest Common Prefix, Remove Nth Node From End of List, Valid Parentheses

Longest Common Prefix
Write a function to find the longest common prefix string amongst an array of strings.  
---------
 grab the first string in array, compare its i-th element to other strings' i-th element

Is there a better solution?
 
class Solution {
public:
    string longestCommonPrefix(vector<string> &strs) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if (strs.size() == 0) {
            return "";
        }
        bool flag = false; // to break the outer for loop
        string prefix = "";
        for (int i=0;i<strs[0].length();i++) {
            for (int j=1;j<strs.size();j++) {
                if (strs[j] == "" || strs[0][i] != strs[j][i]) {
                    // to break the outer for loop
                    flag = true;
                    break;
                }
            }
            
            if (flag) break;
            prefix = prefix + strs[0][i];
        }
        return prefix; 
    }
}; 
Added on Sep-02-2014
Instead of using first string, use 26 alphabet letters to check each string

Remove Nth Node From End of List
Given a linked list, remove the nth node from the end of list and return its head.
For example,
   Given linked list: 1->2->3->4->5, and n = 2.

   After removing the second node from the end, the linked list becomes 1->2->3->5.
Note:
Given n will always be valid.
Try to do this in one pass.
----------
two pointers
 
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode *pre = new ListNode(0), *dummy = pre;
        pre->next = head;
        int k = 0;
        while (head != NULL) {
            head = head->next;
            k++;
        }
        k = k - n;
        while (k > 0) {
            k--;
            pre = pre->next;
        }
    
        pre->next = pre->next->next;
        return dummy->next;
    }
};
Valid Parentheses
Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.
The brackets must close in the correct order, "()" and "()[]{}" are all valid but "(]" and "([)]" are not.
---------------------
use a stack 
class Solution {
public:
    bool isValid(string s) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        stack<char> st;
        for (int i=0;i<s.length();i++) {
            if (s[i] == '(' || s[i] == '[' || s[i] == '{') {
                st.push(s[i]);
            }else {
                if (st.empty()) {
                    return false;
                }
                char c = st.top();
                st.pop();
                if ((s[i] == ')' && c == '(') || (s[i] == '}' && c == '{') || (s[i] == ']' && c == '[')) {
                    ;
                }else return false;
            }
        }
        if (st.empty()) {
            return true;
        }
        return false;
    }
};

Thursday, April 4, 2013

Day 10, 13 Roman to Integer

Roman to Integer
Given a roman numeral, convert it to an integer.
Input is guaranteed to be within the range from 1 to 3999.
---------------------------
first, setup a dictionary, then walk through the whole string
according to the Roman numeral rule, if str[i] < str[i+1], then str[i] should be negative
watch out for the end element of the string, it could be compared to an unknown  value.
 
class Solution {
public:
    int romanToInt(string s) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        unordered_map<char,int> k;
        k['I'] = 1;
        k['V'] = 5;
        k['X'] = 10;
        k['L'] = 50;
        k['C'] = 100;
        k['D'] = 500;
        k['M'] = 1000;
        int sum=0;
        for (int i=0;i<s.length();i++) {
            int sign = 1;
            if (k[s[i]] < k[s[i+1]]) {
                sign = -1;  
            }
            sum = sum + k[s[i]] * sign;
        }
        return sum;
    }
};
Added on Sep-02-2014
Handled final char in string
class Solution {
public:
    unordered_map<char,int> populateMap() {
        unordered_map<char,int> dic;
        dic['I'] = 1;
        dic['V'] = 5;
        dic['X'] = 10;
        dic['L'] = 50;
        dic['C'] = 100;
        dic['D'] = 500;
        dic['M'] = 1000;
        dic['e'] = 0;
        
        return dic;
    }

    int romanToInt(string s) {
        unordered_map<char,int> dic = populateMap();
        int ret = 0;
        s += 'e';
        
        for (int i = 0; i < s.length(); i++) {
            if (dic[s[i]] < dic[s[i + 1]]) {
                ret += dic[s[i + 1]] - dic[s[i]]; 
                i++;
            }else {
                ret += dic[s[i]];
            }    
        }
        return ret;
    }
};

Wednesday, April 3, 2013

Day 9, 9 Palindrome Number

Palindrome Number

Determine whether an integer is a palindrome. Do this without extra space.
Some hints: Could negative integers be palindromes? (ie, -1)
If you are thinking of converting the integer to string, note the restriction of using extra space.
You could also try reversing an integer. However, if you have solved the problem "Reverse Integer", you know that the reversed integer might overflow. How would you handle such case?
There is a more generic way of solving this problem.

 
class Solution {
public:
    bool isPalindrome(int x) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if (x < 0) { 
            return false;
        }
        
        // reverse
        int temp = x;
        int y = 0;
        while (temp>0) { 
            y = 10 * y + temp % 10;
            temp = temp / 10;
        }
        
        if (x != y) {
            return false;
        }
        return true;
    }
};




Tuesday, April 2, 2013

Day 8, 8 String to Integer (atoi)

 String to Integer (atoi)

Implement atoi to convert a string to an integer.
Hint: Carefully consider all possible input cases. If you want a challenge, please do not see below and ask yourself what are the possible input cases.
Notes: It is intended for this problem to be specified vaguely (ie, no given input specs). You are responsible to gather all the input requirements up front.
Requirements for atoi: The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value.
The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function.
If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed.
If no valid conversion could be performed, a zero value is returned. If the correct value is out of the range of representable values, INT_MAX (2147483647) or INT_MIN (-2147483648) is returned.

Solution #1
class Solution {
public:
    int myAtoi(string str) {
        int rt = 0,i = 0;
        int sign = 1;
        while (isspace(str[i])) {
            i++;
        }
        if (str[i] == '-') {
            i++;
            sign = -1;
        }else if (str[i] == '+') i++;
        
        while (i < str.length() && isdigit(str[i])) {
            if (sign == 1 && (rt > 214748364 || (rt == 214748364 && str[i] - '0' > 7))) {
                return INT_MAX;
            }
            if (sign == -1 && (rt > 214748364 || (rt == 214748364 && str[i] - '0' > 8))) {
                return INT_MIN;
            }
            rt = rt * 10 + str[i] - '0';
            i++;
        }
        
        return rt * sign;
    }
};
Solution #2
declare result as long long type;
class Solution {
 public:
  int atoi(const char *str) {
    long long r = 0;
    int i = 0;
    bool negtive = false;
    while(str[i] == ' ')i++;
    if(str[i] == '+') i++;
    else if (str[i] == '-') {
      negtive = true;
      i++;
    }
    for(; str[i] >= '0' && str[i] <= '9'; i++) {
      int d = str[i] - '0';
      if(negtive)r = 10*r - d;
      else r = 10*r + d;
      if( r > numeric_limits<int>::max()) return numeric_limits<int>::max();
      if( r < numeric_limits<int>::min()) return numeric_limits<int>::min();
    }
    return r;
  }

Day 7, 7 Reverse Integer

Reverse Integer
Reverse digits of an integer.

Example1: x = 123, return 321
Example2: x = -123, return -321
Have you thought about this?

Here are some good questions to ask before coding. Bonus points for you if you have already thought through this!

If the integer's last digit is 0, what should the output be? ie, cases such as 10, 100.

Did you notice that the reversed integer might overflow? Assume the input is a 32-bit integer, then the reverse of 1000000003 overflows. How should you handle such cases?

Throw an exception? Good, but what if throwing an exception is not an option? You would then have to re-design the function (ie, add an extra parameter).

Solution #1
class Solution {
public:
    int reverse(int x) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        bool minus = false;
        if (x < 0) {
            x = -x;
            minus = true;
        }
        
        int rev=0;
        while (x > 0) {
            rev = rev * 10 + x%10;
            x = x/10;
        }
        
        if (minus) {
            return -1 * rev;
        }
        return rev;
        
    }
};
检测溢出
class Solution {
public:
    int reverse(int x) {
        int rt = 0,temp = x;
        int sign = 1;
        if (x < 0) {
            sign = -1;
            temp = abs(x);
        }
        
        while (temp > 0) {
            if (rt > INT_MAX / 10 || (rt == INT_MAX / 10 && temp % 10 > 7)) return 0;
            rt = rt * 10 + temp % 10;
            temp /= 10; 
        }
        return rt * sign;
    }
};