LeetCode 97 - Interleaving String


http://buttercola.blogspot.com/2014/09/leetcode-interleaving-string.html
Given s1s2s3, find whether s3 is formed by the interleaving of s1 and s2.
For example,
Given:
s1 = "aabcc",
s2 = "dbbca",

When s3 = "aadbbcbcac", return true.
When s3 = "aadbbbaccc", return false.
X. DP
这道求交织相错的字符串和之前那道 Word Break 拆分词句 的题很类似,就想我之前说的只要是遇到字符串的子序列或是匹配问题直接就上动态规划Dynamic Programming,其他的都不要考虑,什么递归呀的都是浮云,千辛万苦的写了递归结果拿到OJ上妥妥Time Limit Exceeded,能把人气昏了,所以还是直接就考虑DP解法省事些。一般来说字符串匹配问题都是更新一个二维dp数组,核心就在于找出递推公式。那么我们还是从题目中给的例子出发吧,手动写出二维数组dp如下:

复制代码
  Ø d b b c a
Ø T F F F F F
a T F F F F F
a T T T T T F
b F T T F T F
c F F T T T T
c F F F T F T
复制代码

首先,这道题的大前提是字符串s1和s2的长度和必须等于s3的长度,如果不等于,肯定返回false。那么当s1和s2是空串的时候,s3必然是空串,则返回true。所以直接给dp[0][0]赋值true,然后若s1和s2其中的一个为空串的话,那么另一个肯定和s3的长度相等,则按位比较,若相同且上一个位置为True,赋True,其余情况都赋False,这样的二维数组dp的边缘就初始化好了。下面只需要找出递推公式来更新整个数组即可,我们发现,在任意非边缘位置dp[i][j]时,它的左边或上边有可能为True或是False,两边都可以更新过来,只要有一条路通着,那么这个点就可以为True。那么我们得分别来看,如果左边的为True,那么我们去除当前对应的s2中的字符串s2[j - 1] 和 s3中对应的位置的字符相比(计算对应位置时还要考虑已匹配的s1中的字符),为s3[j - 1 + i], 如果相等,则赋True,反之赋False。 而上边为True的情况也类似,所以可以求出递推公式为:
dp[i][j] = (dp[i - 1][j] && s1[i - 1] == s3[i - 1 + j]) || (dp[i][j - 1] && s2[j - 1] == s3[j - 1 + i]);
其中dp[i][j] 表示的是 s2 的前 i 个字符和 s1 的前 j 个字符是否匹配 s3 的前 i+j 个字符,根据以上分析.

https://robinliu.gitbooks.io/algorithms/content/shuang_xu_lie_xing.html
双序列型
状态: f[i][j] 表示第一个 sequence 的前 i 个, 与第二个 sequence 的前 j 个的关系
方程: f[i][j] 第 i 个和第 j 个的匹配关系
初始化: f[i][0] 和 f[0][j]
答案: f[m][n]

state: f[i][j]: 表示 s1 的前 i 个字符和 s2 的前 j 个字符能否组成 s3 的前 i+j 个字符
fucntion: f[i][j] = (f[i-1][j] && s1[i-1] == s3[i+j-1]) || (f[i][j-1] && s2[j-1] == s3[i+j-1])

https://discuss.leetcode.com/topic/7728/dp-solution-in-java
We can use DP to solve this problem. So the steps are:

  • Define boolean dp[str1.length() + 1][str2.length() + 1], where dp[ i ][ j ] : means whether str1.charAt(0) to str1.charAt(i) and str2.charAt(0) to str2.charAt(j) could construct the string str3, from 0 to i + j. 
  • Transit function: 
    • dp[i][j]  = str3.charAt(i + j) == str1.charAt(i) && dp[ i - 1][j] || 
    • str3.charAt(i + j) == str2.charAt(j) && dp[i][j - 1]
  • Initial State 
    • dp[0][0] = true;
    • dp[0][j] = str3.charAt(j) == str2.charAt(j)
    • dp[i][0] = str3.charAt(i) == str1.charAt(i)
  • Final state dp[str1.length()][str2.length()]. 
    public boolean isInterleave(String s1, String s2, String s3) {
        if (s1 == null || s2 == null || s3 == null) {
            return false;
        }
         
        if (s1.length() == 0 && s2.length() == 0 && s3.length() == 0) {
            return true;
        }
         
        if (s1.length() + s2.length() != s3.length()) {
            return false;
        }
         
        boolean[][] dp = new boolean[s1.length() + 1][s2.length() + 1];
        dp[0][0] = true;
         
        for (int i = 1; i <= s2.length(); i++) {
            if (s2.charAt(i - 1) == s3.charAt(i - 1)) {
                dp[0][i] = true;
            } else break;
        }
         
        for (int i = 1; i <= s1.length(); i++) {
            if (s1.charAt(i - 1) == s3.charAt(i - 1)) {
                dp[i][0] = true;
            } else break;
        }
         
        for (int i = 1; i <= s1.length(); i++) {
            for (int j = 1; j <= s2.length(); j++) {
                if (s3.charAt(i + j - 1) == s1.charAt(i - 1)) {
                    dp[i][j] = dp[i - 1][j];
                }
                 
                if (s3.charAt(i + j - 1) == s2.charAt(j - 1)) {
                    dp[i][j] = dp[i][j] || dp[i][j - 1];
                }
            }
        }
         
        return dp[s1.length()][s2.length()];
    }
我们也可以把for循环合并到一起,用if条件来处理边界情况,整体思路和上面的解法没有太大的区别
  public boolean isInterleave(String s1, String s2, String s3) {
    if (s3.length() != s1.length() + s2.length()) {
      return false;
    }
    boolean dp[][] = new boolean[s1.length() + 1][s2.length() + 1];
    for (int i = 0; i <= s1.length(); i++) {
      for (int j = 0; j <= s2.length(); j++) {
        if (i == 0 && j == 0) {
          dp[i][j] = true;
        } else if (i == 0) {
          dp[i][j] = dp[i][j - 1] && s2.charAt(j - 1) == s3.charAt(i + j - 1);
        } else if (j == 0) {
          dp[i][j] = dp[i - 1][j] && s1.charAt(i - 1) == s3.charAt(i + j - 1);
        } else {
          dp[i][j] = (dp[i - 1][j] && s1.charAt(i - 1) == s3.charAt(i + j - 1))
              || (dp[i][j - 1] && s2.charAt(j - 1) == s3.charAt(i + j - 1));
        }
      }
    }
    return dp[s1.length()][s2.length()];

  }
http://www.jiuzhang.com/solutions/interleaving-string/
    public boolean isInterleave(String s1, String s2, String s3) {
        if (s1.length() + s2.length() != s3.length()) {
            return false;
        }
        
        boolean [][] interleaved = new boolean[s1.length() + 1][s2.length() + 1];
        interleaved[0][0] = true;
        
        for (int i = 1; i <= s1.length(); i++) {
            if(s3.charAt(i - 1) == s1.charAt(i - 1) && interleaved[i - 1][0])
                interleaved[i][0] = true;
        }
        
        for (int j = 1; j <= s2.length(); j++) {
            if(s3.charAt(j - 1) == s2.charAt(j - 1) && interleaved[0][j - 1])
                interleaved[0][j] = true;
        }
        
        for (int i = 1; i <= s1.length(); i++) {
            for (int j = 1; j <= s2.length(); j++) {
                if(((s3.charAt(i + j - 1) == s1.charAt(i - 1) && interleaved[i - 1][j]))
                    || ((s3.charAt(i + j - 1)) == s2.charAt(j - 1) && interleaved[i][j - 1]))
                interleaved[i][j] = true;
            }
        }
        
        return interleaved[s1.length()][s2.length()];
    }

X.DP - Space Optimization
https://discuss.leetcode.com/topic/5087/my-solution-in-java-using-dp-time-o-n-m-and-space-o-m
  public boolean isInterleave(String s1, String s2, String s3) {
    if (s3.length() != s1.length() + s2.length()) {
      return false;
    }
    boolean dp[] = new boolean[s2.length() + 1];
    for (int i = 0; i <= s1.length(); i++) {
      for (int j = 0; j <= s2.length(); j++) {
        if (i == 0 && j == 0) {
          dp[j] = true;
        } else if (i == 0) {
          dp[j] = dp[j - 1] && s2.charAt(j - 1) == s3.charAt(i + j - 1);
        } else if (j == 0) {
          dp[j] = dp[j] && s1.charAt(i - 1) == s3.charAt(i + j - 1);
        } else {
          dp[j] = (dp[j] && s1.charAt(i - 1) == s3.charAt(i + j - 1))
              || (dp[j - 1] && s2.charAt(j - 1) == s3.charAt(i + j - 1));
        }
      }
    }
    return dp[s2.length()];

  }
    public boolean isInterleave(String s1, String s2, String s3) {
        if (s1==null || s2==null || s3==null) return false;
        if (s1.length()==0 && s2.length()==0 && s3.length()==0) return true;
        if ((s1.length()+s2.length())!=s3.length()) return false;
        boolean valid[] = new boolean[s2.length()+1];
        valid[0] = false;
        for (int j=1; j<=s2.length(); j++){
            if (s2.charAt(j-1)==s3.charAt(j-1)) valid[j]=true;
        }
        for (int i=1; i<=s1.length(); i++){
            if (s1.charAt(i-1)==s3.charAt(i-1)) valid[0]=true;
            for (int j=1; j<=s2.length(); j++){
                valid[j] = (valid[j] && s1.charAt(i-1)==s3.charAt(i+j-1)) ||
                           (valid[j-1] && s2.charAt(j-1)==s3.charAt(i+j-1));
            }
        }
        return valid[s2.length()];
    }

public static boolean isInterleaveOptz(String s1, String s2, String s3) {
    if (s3.length() != s1.length() + s2.length()) return false;

    boolean[] optimal = new boolean[s2.length() + 1];    //dp optimal
    optimal[0] = true;
    for (int j = 0; j < s2.length(); j++) { //check no s1 char is selected, if s2 could equals to s3
        if (optimal[j] && s2.charAt(j) == s3.charAt(j)) optimal[j + 1] = true;
    }

    for (int i = 0; i < s1.length(); i++) { //check select i-th char in s1
        if (optimal[0] && s1.charAt(i) == s3.charAt(i)) optimal[0] = true;    //no char in s2 is selected
        else optimal[0] = false;
        for (int j = 0; j < s2.length(); j++) {  //select j-th char
            if ((s1.charAt(i) == s3.charAt(i + j + 1) && optimal[j + 1]) ||
                    s2.charAt(j) == s3.charAt(i + j + 1) && optimal[j]) {
                optimal[j + 1] = true;
            } else optimal[j + 1] = false;
        }
    }
    return optimal[s2.length()];
}
时间O(m*n) 空间O(min(m,n))
public boolean isInterleave(String s1, String s2, String s3) {
    if (s1.length() + s2.length() != s3.length()) {
        return false;
    }
    String maxWord = s1.length() > s2.length() ? s1 : s2;
    String minWord = s1.length() > s2.length() ? s2 : s1;
    boolean[]dp = new boolean[minWord.length() + 1];
    dp[0] = true;
   
    for (int i = 0; i < minWord.length(); i++) {
        if (minWord.charAt(i) == s3.charAt(i) && dp[i] == true) {
            dp[i + 1] = true;
        }
    }
    for (int i = 1; i <= maxWord.length(); i++) {
        dp[0] = dp[0] && maxWord.charAt(i - 1) == s3.charAt(i - 1); 
        for (int j = 1; j <= minWord.length(); j++) {
            dp[j] = s3.charAt(i + j - 1) == maxWord.charAt(i - 1) && dp[j] == true || s3.charAt(i + j - 1) == minWord.charAt(j - 1) && dp[j - 1] == true;
            //此处不能再用if判断, 因为dp[j]已经有值 必须要赋值true/false
        }
    }
    
    return dp[minWord.length()];
}

    public boolean isInterleave(String s1, String s2, String s3) {
        // write your code here
     if (s1 == null || s2 == null || s3 == null) return false;
        if (s1.length() == 0 && s2.length() == 0 && s3.length() == 0) return true;
        if ((s1.length() + s2.length()) != s3.length()) return false;
     String shorterString, longerString;
     if (s1.length() < s2.length()) {
     shorterString = s1;
     longerString = s2;
     } else {
     shorterString = s2;
     longerString = s1;
     }
     boolean[] valid = new boolean[shorterString.length() + 1];
     valid[0] = true;
     for (int i = 1; i <= shorterString.length(); i++) {
         if (shorterString.charAt(i-1)==s3.charAt(i-1)) valid[i]=true;
     }
     for (int i = 1; i <= longerString.length(); i++) {
     for (int j = 1; j <= shorterString.length(); j++) {
     valid[j] = (valid[j] && longerString.charAt(i-1)==s3.charAt(i+j-1)) ||
                           (valid[j-1] && shorterString.charAt(j-1)==s3.charAt(i+j-1));
     }
     }
        return valid[shorterString.length()];
    }

X. Recursive version
  1. public boolean isInterleave(String s1, String s2, String s3) {  
  2.       if(s1.length() == 0){  
  3.         if( s2.equals(s3))return true;  
  4.         else return false;  
  5.       }else if(s2.length() == 0){  
  6.         if(s1.equals(s3)) return true;  
  7.         else return false;  
  8.       }  
  9.       if(s3.charAt(0) == s1.charAt(0) && s3.charAt(0) != s2.charAt(0)){  
  10.         return isInterleave(s1.substring(1), s2, s3.substring(1));  
  11.       }else if(s3.charAt(0) == s2.charAt(0) && s3.charAt(0) != s1.charAt(0)){  
  12.         return isInterleave(s1, s2.substring(1), s3.substring(1));  
  13.       }else if(s3.charAt(0) == s1.charAt(0) && s3.charAt(0) == s2.charAt(0)){  
  14.         return isInterleave(s1.substring(1), s2, s3.substring(1)) || isInterleave(s1, s2.substring(1), s3.substring(1));  
  15.       }else{  
  16.         return false;  
  17.       }  
  18.   }  


既然DFS可以,那么BFS也就坐不住了,也要出来浪一波。这里我们需要用队列queue来辅助运算,如果将解法一讲解中的那个二维dp数组列出来的TF图当作一个迷宫的话,那么BFS的目的就是要从(0, 0)位置找一条都是T的路径通到(n1, n2)位置,这里我们还要使用哈希集合,不过此时保存到是已经遍历过的位置,队列中还是存key值,key值的encode方法跟上面DFS解法的相同,初识时放个0进去。然后我们进行while循环,循环条件除了q不为空,还有一个是k小于n3,因为匹配完s3中所有的字符就结束了。然后由于是一层层的遍历,所以要直接循环queue中元素个数的次数,在for循环中,对队首元素进行解码,得到i和j值,如果i小于n1,说明s1还有剩余字符,如果s1当前字符等于s3当前字符,那么把s1的下一个位置i+1跟j一起加码算出key值,如果该key值不在于集合中,则加入集合,同时加入队列queue中;同理,如果j小于n2,说明s2还有剩余字符,如果s2当前字符等于s3当前字符,那么把s2的下一个位置j+1跟i一起加码算出key值,如果该key值不在于集合中,则加入集合,同时加入队列queue中。for循环结束后,k自增1。最后如果匹配成功的话,那么queue中应该只有一个(n1, n2)的key值,且k此时等于n3,所以当queue为空或者k不等于n3的时候都要返回false
https://discuss.leetcode.com/topic/6562/8ms-c-solution-using-bfs-with-explanation
If we expand the two strings s1 and s2 into a chessboard, then this problem can be transferred into a path seeking problem from the top-left corner to the bottom-right corner. The key is, each cell (y, x) in the board corresponds to an interval between y-th character in s1 and x-th character in s2. And adjacent cells are connected with like a grid. A BFS can then be efficiently performed to find the path.
Better to illustrate with an example here:
Say s1 = "aab" and s2 = "abc". s3 = "aaabcb". Then the board looks like
o--a--o--b--o--c--o
|     |     |     |
a     a     a     a
|     |     |     |
o--a--o--b--o--c--o
|     |     |     |
a     a     a     a
|     |     |     |
o--a--o--b--o--c--o
|     |     |     |
b     b     b     b
|     |     |     |
o--a--o--b--o--c--o
Each "o" is a cell in the board. We start from the top-left corner, and try to move right or down. If the next char in s3 matches the edge connecting the next cell, then we're able to move. When we hit the bottom-right corner, this means s3 can be represented by interleaving s1 and s2. One possible path for this example is indicated with "x"es below:
x--a--x--b--o--c--o
|     |     |     |
a     a     a     a
|     |     |     |
o--a--x--b--o--c--o
|     |     |     |
a     a     a     a
|     |     |     |
o--a--x--b--x--c--x
|     |     |     |
b     b     b     b
|     |     |     |
o--a--o--b--o--c--x
Note if we concatenate the chars on the edges we went along, it's exactly s3. And we went through all the chars in s1 and s2, in order, exactly once.
Therefore if we view this board as a graph, such path finding problem is trivial with BFS. I use an unordered_map to store the visited nodes, which makes the code look a bit complicated. But a vector should be enough to do the job.
Although the worse case timeis also O(mn), typically it doesn't require us to go through every node to find a path. Therefore it's faster than regular DP than average.
    public boolean isInterleave(String s1, String s2, String s3) {
        if (s1.length() + s2.length() != s3.length()) return false;
        boolean[][] visited = new boolean[s1.length() + 1][s2.length() + 1];
        Queue<int[]> queue = new LinkedList<>();
        queue.offer(new int[]{0, 0});
        while (!queue.isEmpty()) {
            int[] p = queue.poll();
            if (visited[p[0]][p[1]]) continue;
            if (p[0] == s1.length() && p[1] == s2.length()) return true;
            
            if (p[0] < s1.length() && s1.charAt(p[0]) == s3.charAt(p[0] + p[1]))
                queue.offer(new int[]{p[0] + 1, p[1]});
            if (p[1] < s2.length() && s2.charAt(p[1]) == s3.charAt(p[0] + p[1]))
                queue.offer(new int[]{p[0], p[1] + 1});
            visited[p[0]][p[1]] = true;
        }
        return false;
    }

struct MyPoint {
    int y, x; 
    bool operator==(const MyPoint &p) const {
        return p.y == y && p.x == x;
    }
};
namespace std {
    template <>
    struct hash<MyPoint> {
        size_t operator () (const MyPoint &f) const {
            return (std::hash<int>()(f.x) << 1) ^ std::hash<int>()(f.y);
        }
    };
}

class Solution {
public:
    bool isInterleave(string s1, string s2, string s3) {
        if (s1.size() + s2.size() != s3.size()) return false;

        queue<MyPoint> q;
        unordered_set<MyPoint> visited;
        bool isSuccessful = false;
        int i = 0;

        q.push(MyPoint { 0, 0 });
        q.push(MyPoint { -1, -1 });
        while (!(1 == q.size() && -1 == q.front().x)) {
            auto p = q.front();
            q.pop();
            if (p.y == s1.size() && p.x == s2.size()) {
                return true;
            }
            if (-1 == p.y) {
                q.push(p);
                i++;
                continue;
            }
            if (visited.find(p) != visited.end()) { continue; }
            visited.insert(p);

            if (p.y < s1.size()) { // down
                if (s1[p.y] == s3[i]) { q.push(MyPoint { p.y + 1, p.x }); }
            }
            if (p.x < s2.size()) { // right 
                if (s2[p.x] == s3[i]) { q.push(MyPoint { p.y, p.x + 1 }); }
            }
        }
        return false;
    }
};
Imagine a grid, which x-axis and y-axis are s1 and s2, matching s3 is the same as
finding a path from (0,0) to (len1, len2). It actually becomes a
BFS on grid. Since we don't need exact paths, a HashSet of
coordinates is used to eliminate duplicated paths.
    public boolean isInterleave(String s1, String s2, String s3) {
        int len1 = s1.length(),
            len2 = s2.length(),
            len3 = s3.length();
        if (len1 + len2 != len3) return false;
        Deque<Integer> queue = new LinkedList<>();
        int matched = 0;
        queue.offer(0);
        Set<Integer> set = new HashSet<>();
        while (queue.size() > 0 && matched < len3) {
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                int p1 = queue.peek() / len3,
                    p2 = queue.peek() % len3;
                queue.poll();
                if (p1 < len1 && s1.charAt(p1) == s3.charAt(matched)) {
                    int key = (p1 + 1) * len3 + p2;
                    if (!set.contains(key)) {
                        set.add(key);
                        queue.offer(key);
                    }
                }
                if (p2 < len2 && s2.charAt(p2) == s3.charAt(matched)) {
                    int key = p1 * len3 + (p2 + 1);
                    if (!set.contains(key)) {
                        set.add(key);
                        queue.offer(key);
                    }
                }
            }
            matched++;
        }
        return queue.size() > 0 && matched == len3;
    }
https://discuss.leetcode.com/topic/19900/python-dp-solutions-o-m-n-o-n-space-bfs-dfs/2
def isInterleave(self, s1, s2, s3):
    r, c, l= len(s1), len(s2), len(s3)
    if r+c != l:
        return False
    queue, visited = [(0, 0)], set((0, 0))
    while queue:
        x, y = queue.pop(0)
        if x+y == l:
            return True
        if x+1 <= r and s1[x] == s3[x+y] and (x+1, y) not in visited:
            queue.append((x+1, y)); visited.add((x+1, y))
        if y+1 <= c and s2[y] == s3[x+y] and (x, y+1) not in visited:
            queue.append((x, y+1)); visited.add((x, y+1))
    return False

X. DFS + cache
  public boolean is_Interleave(String s1, int i, String s2, int j, String s3, int k, int[][] memo) {
    if (i == s1.length()) {
      return s2.substring(j).equals(s3.substring(k));
    }
    if (j == s2.length()) {
      return s1.substring(i).equals(s3.substring(k));
    }
    if (memo[i][j] >= 0) {
      return memo[i][j] == 1 ? true : false;
    }
    boolean ans = false;
    if (s3.charAt(k) == s1.charAt(i) && is_Interleave(s1, i + 1, s2, j, s3, k + 1, memo)
        || s3.charAt(k) == s2.charAt(j) && is_Interleave(s1, i, s2, j + 1, s3, k + 1, memo)) {
      ans = true;
    }
    memo[i][j] = ans ? 1 : 0;
    return ans;
  }

  public boolean isInterleave(String s1, String s2, String s3) {
    int memo[][] = new int[s1.length()][s2.length()];
    for (int i = 0; i < s1.length(); i++) {
      for (int j = 0; j < s2.length(); j++) {
        memo[i][j] = -1;
      }
    }
    return is_Interleave(s1, 0, s2, 0, s3, 0, memo);

  }
https://leetcode.com/articles/interleaving-strings/
Time complexity : O(2^{m+n})m is the length of s1 and n is the length of s2.
  public boolean is_Interleave(String s1, int i, String s2, int j, String res, String s3) {
    if (res.equals(s3) && i == s1.length() && j == s2.length())
      return true;
    boolean ans = false;
    if (i < s1.length())
      ans |= is_Interleave(s1, i + 1, s2, j, res + s1.charAt(i), s3);
    if (j < s2.length())
      ans |= is_Interleave(s1, i, s2, j + 1, res + s2.charAt(j), s3);
    return ans;

  }

  public boolean isInterleave(String s1, String s2, String s3) {
    return is_Interleave(s1, 0, s2, 0, "", s3);

  }

https://www.cnblogs.com/higerzhang/p/4122234.html
然后就想用动态规划了,一开始我定义dp[i][j][k],表示s1的前i个和s2的前j个是否和s3的前k个匹配。bool型的。如下:
后面觉得不要用三维可以,可以把dp的第三维度干掉。dp[i][j]就表示s1的前i个和s2的前j个是否和s3的前i+j个匹配
    bool isInterleave(string s1, string s2, string s3) 
    {
        int len1 = s1.size(), len2 = s2.size(), len3 = s3.size();
        if (len1 == 0) return s2 == s3;
        if (len2 == 0) return s1 == s3;
        if (len1 + len2 != len3) return false;
        bool dp[len1+1][len2+1][len3+1];
        
        for (int i = 1; i <= len3; ++i)
        {
            if (i <= len1)
                dp[i][0][i] = s1[i-1] == s3[i-1];
            if (i <= len2)
                dp[0][i][i] = s2[i-1] == s3[i-1];
        }
        
        for (int i = 1; i <= len1; ++i)
            for (int j = 1; j <= len2; ++j)
            {
                int k = i + j;
                if (s1[i-1] == s3[k-1] && s1[i-1] != s2[j-1])
                    dp[i][j][k] = dp[i-1][j][k-1];
                else if (s2[j-1] == s3[k-1] && s1[i-1] != s2[j-1])
                    dp[i][j][k] = dp[i][j-1][k-1];
                else if (s1[i-1] == s2[j-1] && s1[i-1] == s3[k-1])
                    dp[i][j][k] = (dp[i][j-1][k-1] || dp[i-1][j][k-1]);
                else 
                    dp[i][j][k] = 0;
                }
        return dp[len1][len2][len3];
    }


Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts