sourcecode

Sunday, December 30, 2012

Valid Parentheses


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.
class Solution {
public:
    bool isValid(string s) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        stack<char> v;
        for(int ii = 0; ii < s.length(); ++ii){
            switch(s[ii]){
                case '{':
                case '[':
                case '(':
                    v.push(s[ii]);
                    break;
                case '}':
                case ']':
                case ')':
                    if (v.empty()) return false;
                    char c = v.top();//expect {[(
                    if (c+1 == s[ii] || c+2 == s[ii]) v.pop();//ASCII
                    else return false;
            }
        }
        return v.empty();
    }
};

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.
class Solution {
    bool validate(vector<char> &num){
        vector<bool> v(10,false);
        for(int ii = 0; ii < num.size(); ++ii){
            if (num[ii] == '.') continue;
            int index = num[ii] - '0';
            if (v[index]) return false;
            else (v[index] = true);
        }
        return true;
    }
public:
    bool isValidSudoku(vector<vector<char> > &board) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        for(int ii = 0; ii < board.size(); ++ii){
            if (!validate(board[ii])) return false;
        }
        
        for(int col = 0; col < board.size(); ++col){
            vector<char> v;
            for(int row = 0; row < board.size(); ++row){
                v.push_back(board[row][col]);
            }
            if (!validate(v)) return false;
        }
        
        for(int start = 0; start < 3; ++start){
            for(int first = 0; first < 3; ++first){
                vector<char> block;
                for(int line = 0; line < 3; ++line){
                    for(int cell = 0; cell < 3; ++cell){
                        int row = start * 3 + line;
                        int col = first * 3 + cell;
                        block.push_back(board[row][col]);
                    }
                }
                if (!validate(block)) return false;
            }
        }
        return true;
    }
};

Validate Binary Search Tree


Validate Binary Search Tree
Given a binary tree, determine if it is a valid binary search tree (BST).
Assume a BST is defined as follows:
  • The left subtree of a node contains only nodes with keys less than the node's key.
  • The right subtree of a node contains only nodes with keys greater than the node's key.
  • Both the left and right subtrees must also be binary search trees.
/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
    vector<int> v;
    void inOrder(TreeNode *root){
        if (!root) return;
        inOrder(root->left);
        v.push_back(root->val);
        inOrder(root->right);
        return;
    }
public:
    bool isValidBST(TreeNode *root) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        v.clear();
        inOrder(root);
        for(int ii = 1; ii < v.size(); ++ii){
            if (v[ii] <= v[ii-1]) return false;
        }
        return true;
    }
};

Saturday, December 29, 2012

Wildcard Matching

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

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

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

Some examples:
isMatch("aa","a") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "*") → true
isMatch("aa", "a*") → true
isMatch("ab", "?*") → true
isMatch("aab", "c*a*b") → false

First Solution is recursive. Good for concept, but not efficient enough to pass large test sets:

class Solution {
public:
    bool isMatch(const char *s, const char *p) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if (*p == '*'){//return true;
            while(*p == '*') ++p;
            if (*p == '\0') return true;
            while(*s != '\0' && !isMatch(s,p)){
                ++s;                
            }
            return *s != '\0';
        }
        else if (*p == '\0' || *s == '\0') return *p == *s;
        else if (*p == *s || *p == '?') return isMatch(++s,++p);
        else return false;
    }
};
Dynamic Programming, iteration version, both time and memory efficient:
class Solution {
public:
    bool isMatch(const char *s, const char *p) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if (!*s && !*p) return true;
        
        int ms_max = 1;//size of *s
        const char* ss = s;
        while(*ss){ ++ms_max;++ss;}
        int np_max = 1;
        const char* pp = p;
        while(*pp){if(*pp!='*')++np_max;++pp;}
        if(ms_max < np_max) return false;
        
        vector<vector<bool> > r(2, vector<bool>(ms_max, false));
        bool flag = 1;
        r[0][0] = true;
        do{//*p
            int ms = 1;
            ss = s;
            if (*p == '*'){
                while(*p == '*') ++p;
                --p;
                r[flag][0] = r[!flag][0];
                for( ;ms <= ms_max; ++ms){//up and left
                    if (r[!flag][ms] || r[flag][ms-1]) break;
                    else r[flag][ms] = false;
                }
                for(;ms <= ms_max; ++ms){
                    r[flag][ms] = true;
                }
            }
            else{
                do{
                    bool r_flag = false;
                    if (*ss == *p || *p == '?'){
                        r_flag = r[!flag][ms-1];//diagnal
                    }
                    r[flag][ms]=r_flag;
                    ++ms;++ss;
                }while(*ss);//*s
                r[flag][0] = false;
            }
            ++p;
            flag = !flag;
        }while(*p);
        return r[!flag][ms_max-1];
    }
};

The thinking process:

The recursive method is intuitive and gives great insight of the matching process. If we neglect the boundary cases for a moment, there are three basic cases when we try to match the characters in s[] and p[]:
1.  No match. Simply return false. This is the last case in the program.
2. Single match. Either *s == *p, or *p == '?'. The return value of this case depends on the result of the rest parts of both s[] and p[] (recursion call), which start at the 'diagonal' position by advancing both s[] and p[] by 1 (++s, ++p)
3. Star case, i.e. when *p == '*'. This is where the complication comes in. A star can match 0, 1, 2, ..., to the end of string s[].  So, as long as one of the substrings match (recursion call), after advance over *, it returns true. This case returns false only after exhausting all possible substrings without a match.

After we have some sense on the dependencies of each step, learned from the recursive function calls, we can set up our dynamic programming frame. For example s[] = "abcdef" and p[] = "a?c*f"

The  strings are indexed 1 for convenience. Now let's directly apply the rules learned from the recursion method:

The arrow means "depends on" or "recursion call". The cells without a match can be pre-filled with FALSE's. The tail cell '\0' '\0' is marked TRUE.

We eventually want to know cell(0,0), but we have to know cell(1)first;
s[1] == p[1] gives case 2, so cell(1) depends on cell(2);
p[2] == '?' gives case 2, so cell(2) depends on cell(3);
s[3] == p[3] gives case 2, so cell(3) depends on cell(4);
p[4] == '*' gives case 3, so cell(4) depends on all the crimson shaded cells. As long as one of the shaded cells is TRUE, Cell(4) is TRUE.
...
p[5] == s[6] gives case 2, so cell(5) depends on the tail '\0','\0' case, which is TRUE. So cell(5) = TRUE.
Then we trackback, just as the recursive functions.
cell(0) = cell(1) = cell(2) = cell(3) = cell(4) = cell(5) = TRUE.
At last the function returns TRUE.

The steps above is using dynamic programming matrix, but follow the recursion process. Now we do the REAL dynamic programming. Note that the problem is symmetric, which means you can match the strings from left to right, or from right to left, they are identical. In the recursion method, the actual result propagates from the bottom right corner to the up left corner. In dynamic programming, we want to start with row one, so we can flip the whole dependency graph. Again the arrows mean dependencies, or get value from.

All the non-matching cells are pre-filled with FALSE's. The only initial TRUE is at cell(0), which is also the case when you match two NULL strings. So now you just need a matrix size(s)*size(p), and fill the cells row by row according to the three rules:
1. No matching: fill FALSE;
2. Matching, or '?': copy the value from previous diagonal cell
3. '*': Look up all cells to the left, and look up the cells to the left of previous row, and the cell directly above ---- if there is at least one TRUE, fill TURE; otherwise fill FALSE

Finally return the value of the last cell.

There are some more tricks in practice.
Firstly, successive '*' is equivalent to a single '*', so we may suppress them together. After doing this, the number of '*'s is at most size(p)/2. So the worst run time is O(m*n + m^2), where m=size(p) and n=size(s).
Also consider that after removing all '*'s, size(p) <= size(s), which means m is at most 2n for the worst case, so that m = O(n). Thus the worst run time is O(m*n).

Secondly, the matrix is updated row by row, and even the '*' case requires two latest rows. So it is possible to have a space efficient way solve the matching problem by using two size(s) arrays.

Monday, December 10, 2012

Word Search


Word Search
Given a 2D board and a word, find if the word exists in the grid.
The word can be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once.
For example,
Given board =
[
  ["ABCE"],
  ["SFCS"],
  ["ADEE"]
]
word = "ABCCED", -> returns true,
word = "SEE", -> returns true,
word = "ABCB", -> returns false.
class Solution {
    vector<vector<char> >* b;
    string* s;
    vector<vector<bool> > visit;
    int southBound, eastBound;//northBound  and westBound are 0
    int maxIndex;
    bool check(int x, int y, int nn){//(x,y) on board, string nn index
        if (x < 0 || x > eastBound || y < 0 || y > southBound) return false;
        if (visit[y][x]) return false;
        if ((*b)[y][x] != (*s)[nn]) return false;
        //matched
        if (nn == maxIndex) return true;        
        visit[y][x] = true;
        bool flag = check(x+1,y,nn+1)||check(x,y+1,nn+1)||check(x-1,y,nn+1)||check(x,y-1,nn+1);
        visit[y][x] = false;
        return flag;        
    }
public:
    bool exist(vector<vector<char> > &board, string word) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        b = &board;
        s = &word;
        if (b->empty()) return false;
        southBound = b->size()-1;
        if ((*b)[0].empty()) return false;
        eastBound = (*b)[0].size()-1;
        maxIndex = word.length() -1;
        visit.assign(b->size(), vector<bool>((*b)[0].size(), false));
        
        for(int ii = 0; ii <= southBound; ++ii){
            for(int jj = 0; jj <= eastBound; ++jj){
                bool flag = check(jj,ii,0);
                if (flag) return true;
            }
        }
        return false;
    }
};

ZigZag Conversion


The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)
P   A   H   N
A P L S I I G
Y   I   R
And then read line by line: "PAHNAPLSIIGYIR"
Write the code that will take a string and make this conversion given a number of rows:
string convert(string text, int nRows);
convert("PAYPALISHIRING", 3) should return "PAHNAPLSIIGYIR".

For an input string "aaaaaaaaaaaaaa", you are getting an output | / | / | like pattern:
a___a___a
a__aa__aa
a_a_a_a_a
aa__aa__a
a___a___a
class Solution {
public:
    string convert(string s, int nRows) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function  
        string r(s);
        if (nRows <= 1) return r;
        int rii = 0;
        for(int nn = 0; nn < s.size(); nn += (nRows-1)*2){//first row
            r[rii++] = s[nn];
        }
        for(int row = 1; row+1 < nRows; ++row){
            for(int nn = row; nn < s.size(); nn += (nRows-1)*2){
                r[rii++] = s[nn];
                int secondIndex = nn + (nRows-row-1)*2;
                if (secondIndex < s.size()) r[rii++] = s[secondIndex];
            }
        }
        for(int nn = nRows-1; nn < s.size(); nn += (nRows-1)*2){//last row
            r[rii++] = s[nn];
        }
        
        return r;
    }
};