LeetCode 756 - Pyramid Transition Matrix


Related:
String pyramids transition matrix - Airbnb
https://leetcode.com/problems/pyramid-transition-matrix/
We are stacking blocks to form a pyramid. Each block has a color which is a one letter string, like `'Z'`.
For every block of color `C` we place not in the bottom row, we are placing it on top of a left block of color `A` and right block of color `B`. We are allowed to place the block there only if `(A, B, C)` is an allowed triple.
We start with a bottom row of bottom, represented as a single string. We also start with a list of allowed triples allowed. Each allowed triple is represented as a string of length 3.
Return true if we can build the pyramid all the way to the top, otherwise false.
Example 1:
Input: bottom = "XYZ", allowed = ["XYD", "YZE", "DEA", "FFF"]
Output: true
Explanation:
We can stack the pyramid like this:
    A
   / \
  D   E
 / \ / \
X   Y   Z

This works because ('X', 'Y', 'D'), ('Y', 'Z', 'E'), and ('D', 'E', 'A') are allowed triples.
Example 2:
Input: bottom = "XXYX", allowed = ["XXX", "XXY", "XYX", "XYY", "YXZ"]
Output: false
Explanation:
We can't stack the pyramid to the top.
Note that there could be allowed triples (A, B, C) and (A, B, D) with C != D.
Note:
  1. bottom will be a string with length in range [2, 8].
  2. allowed will have length in range [0, 200].
  3. Letters in all strings will be chosen from the set {'A', 'B', 'C', 'D', 'E', 'F', 'G'}
http://www.cnblogs.com/grandyang/p/8476646.html
这道题让我们累一个金字塔,用字母来代表每块砖的颜色,给了一个allowed数组,里面都是长度为三的字符串,比如“ABC”表示C可以放在A和B的上方,注意AB上面也可以放其他的,比如“ABD”也可以同时出现,不过搭积木的时候只能选择一种。给了我们一个bottom字符串,是金字塔的底层,问我们能不能搭出一个完整的金字塔。那么实际上我们就是从底层开始,一层一层的向上来累加,直到搭出整个金字塔。我们先来看递归的解法,首先由于我们想快速知道两个字母上方可以放的字母,需要建立基座字符串和上方字符集合之间的映射,由于上方字符可以不唯一,所以用个HashSet来放字符。我们的递归函数有三个参数,当前层字符串cur,上层字符串above,还有我们的HashMap。如果cur的大小为2,above的大小为1,那么说明当前已经达到金字塔的顶端了,已经搭出来了,直接返回true。否则看,如果上一层的长度比当前层的长度正好小一个,说明上一层也搭好了,我们现在去搭上上层,于是调用递归函数,将above当作当前层,空字符串为上一层,将调用的递归函数结果直接返回。否则表示我们还需要继续去搭above层,我们先算出above层的长度pos,然后从当前层的pos位置开始取两个字符,就是above层接下来需要搭的字符的基座字符,举个例子如下:
  D   
 / \ / \
A   B   C
我们看到现在above层只有一个D,那么pos为1,在cur层1位置开始取两个字符,得到"BC",即是D的下一个位置的字符的基座字符串base。取出了base后,如果HashMap中有映射,则我们遍历其映射的字符集合中的所有字符,对每个字符都调用递归函数,此时above字符串需要加上这个遍历到的字符,因为我们在尝试填充这个位置,如果有返回true的,那么当前递归函数就返回true了,否则最终返回false.
我们在每层字符串作为底座的基础上,向上面建立新的一层。所以是个递归过程。建立的方式是通过允许的组合,这个组合是我们可以通过下面的这两块砖来获得上面可以累加什么砖的方式。

所以,用curr表示当前层,用above表示上层。当curr大小为2,above为1,那么金字塔完成。如果curr = above + 1,说明上面这层已经弄好了,下面使用above来作为当前层,继续递归。

如果上面两个都不满足,说明需要继续堆积above,做的方式是在应该继续堆积的位置上,找出能堆积哪些字符,并把这个字符堆积上去,做递归。
    bool pyramidTransition(string bottom, vector<string>& allowed) {   
        unordered_map<string, unordered_set<char>> m;
        for (string str : allowed) {
            m[str.substr(0, 2)].insert(str[2]);
        }
        return helper(bottom, "", m);
    }
    bool helper(string cur, string above, unordered_map<string, unordered_set<char>>& m) {
        if (cur.size() == 2 && above.size() == 1) return true;
        if (above.size() == cur.size() - 1) return helper(above, "", m);
        int pos = above.size();
        string base = cur.substr(pos, 2);
        if (m.count(base)) {
            for (char ch : m[base]) {
                if (helper(cur, above + string(1, ch), m)) {
                    return true;
                }
            }
        }
        return false;
    }
https://www.acwing.com/solution/leetcode/content/189/
https://my.oschina.net/liyurong/blog/1616709
    public boolean pyramidTransition(String bottom, List<String> allowed) {
        Map<String,List<String>> map = new HashMap<>();//键为左右节点字符串,值为根节点的集合
        for (String str : allowed){
            String key = str.substring(0,2);
            if (! map.containsKey(key)){
                map.put(key,new ArrayList<>());
            }
            map.get(key).add(str.substring(2));
        }
        return dfs(map,bottom,new StringBuilder(),0);
    }
    public boolean dfs(Map<String,List<String>> map,String bottom,StringBuilder nextBottom,int p){
        if (p == bottom.length() - 1){//完成一行,更新bottom和p
            bottom = nextBottom.toString();
            nextBottom = new StringBuilder();
            p = 0;
        }
        if (bottom.length() == 1) return true;
        String key = bottom.substring(p,p + 2);
        if (map.containsKey(key)){
            for (String val : map.get(key)){
                nextBottom.append(val);
                if (dfs(map,bottom,nextBottom,p + 1)) return true;
                nextBottom.setLength(nextBottom.length() - 1);//还原
            }
        }
        return false;
    }
http://hehejun.blogspot.com/2018/10/leetcodepyramid-transition-matrix.html
这道题首先我们第一反应是考虑BFS或者DFS,但仔细考虑过后BFS事实上是做不了的,比如对于ABC和{ABD, ABE, BCK},在AB的时候我们有两种选择,而我们BFS只能取一个。所以我们需要用DFS来遍历所有的可能,从最底层开始直到最顶层。对于每个合法的block,我们可以用bit来存,因为只会用到7个字符,比如我们用map[a][c]表示AC后面能够接的字符,每一位代表从a到g的每个字符。时间复杂度O(N^k),N为最底层的长度,k为所用的字符数量
   bool pyramidTransition(string bottom, vector<string>& allowed) {
      int len = bottom.size();
      vector<vector<int>> pyramid(8, vector<int>(8, 0)), map(7, vector<int>(7, 0));
      for (auto& str : allowed)
         map[str[0] - 'A'][str[1] - 'A'] |= 1 << (str[2] - 'A');
      for (int i = 0; i < bottom.size(); ++i)pyramid[len - 1][i] = bottom[i] - 'A';
      return dfs(pyramid, map, len - 1, 0);
   }

private:
   //N length of current row
   //i index of current column
   bool dfs(vector<vector<int>>& pyramid, vector<vector<int>>& map, int N, int i)
   {
      if (N == 1 && i == 1)return true;
      if (i == N)return dfs(pyramid, map, N - 1, 0);
      int bit = map[pyramid[N][i]][pyramid[N][i + 1]];
      for (int j = 0; j < 7; ++j)
      {
         if (bit & (1 << j))
         {
            pyramid[N - 1][i] = j;
            if (dfs(pyramid, map, N, i + 1))
               return true;
         }
      }
      return false;
   }

X. Multiple phrases DFS
https://leetcode.com/problems/pyramid-transition-matrix/discuss/113054/Java-solution-map-%2B-backtracking
    public boolean pyramidTransition(String bottom, List<String> allowed) {
        Map<String, List<String>> map = new HashMap<>();
        for (String s : allowed) {
            String key = s.substring(0,2);
            if (!map.containsKey(key)) map.put(key, new ArrayList<String>());
            map.get(key).add(s.substring(2));
        }
        
        return helper(bottom, map);
    }
    
    private boolean helper(String bottom, Map<String, List<String>> map) {
        if(bottom.length() == 1) return true;
        for (int i = 0; i<bottom.length()-1; i++) {
            if (!map.containsKey(bottom.substring(i,i+2))) return false;
        }
        List<String> ls = new ArrayList<>();
        getList(bottom, 0, new StringBuilder(), ls, map);
        for (String s : ls) {
            if (helper(s, map)) return true;
        }
        return false;
    }
    
    private void getList(String bottom, int idx, StringBuilder sb, List<String> ls, Map<String, List<String>> map) {
        if (idx == bottom.length() - 1) {
            ls.add(sb.toString());
            return;
        }
        for (String s : map.get(bottom.substring(idx, idx+2))) {
            sb.append(s);
            getList(bottom, idx + 1, sb, ls, map);
            sb.deleteCharAt(sb.length()-1);
        }
    }

X. Backtrack + DFS + Cache
https://leetcode.com/problems/pyramid-transition-matrix/discuss/113062/C%2B%2B-passed-counter-example-DFS-with-memoization-6-ms
Theoretically, BFS should work. We can use unordered_set to keep all possible strings for each level. Then move up and generate possible combinations for next level. When reaching the top, if the set is non-empty, return true. However, it will result in TLE. The advantage of DFS is early termination. Once we find a valid solution, we don't have to traverse the whole tree, although the worse case runtime is the same.
A couple optimization:
  1. memoization: unordered_set invalid, to keep all the strings that won't work.
  2. 2D vector to keep edges, such as "ABE".
  3. early termination if a string cannot generate a string of next level. For example, "ABFE" while there is no edge of "BF#".
    private Map<Character, Map<Character, List<Character>>> map = new HashMap<>();
    private Map<String, Boolean> memo = new HashMap<>();
    
    // is it possible to build a pyramid upon "bottom"?
    private boolean dfs1(String bottom) {
        if (bottom.length() == 1) {
            return true;
        }
        if (memo.get(bottom) != null) {
            return memo.get(bottom);
        }
        
        boolean res = dfs2(bottom, new StringBuilder(), 0);
        memo.put(bottom, res);
        return res;
    }
    
    // is it possible to build a pyramid upon "bottom"
    // given the first |next| elements has been fixed in ceiling
    private boolean dfs2(String bottom, StringBuilder ceiling, int next) {
        if (next == bottom.length() - 1) {
            return dfs1(ceiling.toString());
        }
        // consider the next element in ceiling
        if (map.get(bottom.charAt(next)) == null) {
            return false;
        }
        if (map.get(bottom.charAt(next)).get(bottom.charAt(next+1)) == null) {
            return false;
        }
        for (char ch : map.get(bottom.charAt(next)).get(bottom.charAt(next+1))) {
            ceiling.append(ch);
            if (dfs2(bottom, ceiling, next+1)) {
                return true;
            }
            ceiling.deleteCharAt(ceiling.length() - 1);
        }
        return false;
    }
    
    
    public boolean pyramidTransition(String bottom, List<String> allowed) {
        for (String edge : allowed) {
            char a = edge.charAt(0);
            char b = edge.charAt(1);
            char c = edge.charAt(2);
            
            map.putIfAbsent(a, new HashMap<>());
            map.get(a).putIfAbsent(b, new ArrayList<>());
            map.get(a).get(b).add(c);
        }
        
        return dfs1(bottom);
    }

X. https://leetcode.com/problems/pyramid-transition-matrix/discuss/170870/concise-C%2B%2B-recursive-solution-(10-line)


Dealing with layer is a little bit awkward, here I use a space character to separate the layer and then it turns to a simple string. 
    public boolean pyramidTransition(String bottom, List<String> allowed) {
        Map<String, List<Character>> map = new HashMap<>();
        for (String a : allowed) {
            String b = a.substring(0, 2);
            if (!map.containsKey(b)) map.put(b, new ArrayList<>());
            map.get(b).add(a.charAt(2));
        }
        return canStack(bottom + ' ', map);
    }
    
    boolean canStack(String s, Map<String, List<Character>> map) {
        if (s.length() == 1) return true;
        String b = s.substring(0, 2);
        if (b.charAt(1) == ' ') return canStack(s.substring(2, s.length()) + ' ', map);
        for (Character c : map.getOrDefault(b, new ArrayList<>())) {
            if (canStack(s.substring(1, s.length()) + c, map)) return true;
        }
        return false;
    }
X. https://leetcode.com/problems/pyramid-transition-matrix/discuss/113054/Java-solution-map-%2B-backtracking
    public boolean pyramidTransition(String bottom, List<String> allowed) {
        Map<String, List<String>> map = new HashMap<>();
        for (String s : allowed) {
            String key = s.substring(0,2);
            if (!map.containsKey(key)) map.put(key, new ArrayList<String>());
            map.get(key).add(s.substring(2));
        }
        
        return helper(bottom, map);
    }
    
    private boolean helper(String bottom, Map<String, List<String>> map) {
        if(bottom.length() == 1) return true;
        for (int i = 0; i<bottom.length()-1; i++) { //首先判断上一层无法构建的情况,如果无法构建直接return false
            if (!map.containsKey(bottom.substring(i,i+2))) return false;
        }
        List<String> ls = new ArrayList<>();//使用dfs的方式找到上一层所有可能结果
        getList(bottom, 0, new StringBuilder(), ls, map);
        for (String s : ls) {//遍历所有结果进行递归搜索
            if (helper(s, map)) return true;
        }
        return false;
    }
    // dfs的方式找到所有可能的上一层的结果
    // 结果存储到 candidates 数组中
    // cur 存储当前dfs的进度
    private void getList(String bottom, int idx, StringBuilder sb, List<String> ls, Map<String, List<String>> map) {
        if (idx == bottom.length() - 1) {
            ls.add(sb.toString());
            return;
        }
        for (String s : map.get(bottom.substring(idx, idx+2))) {
            sb.append(s);
            getList(bottom, idx + 1, sb, ls, map);
            sb.deleteCharAt(sb.length()-1);
        }
    }

X. DP - Wrong
Approach #1: State to State Transition [Wrong Answer]
Intuition and Algorithm
We model the states that blocks can be in. Each state is a binary number where the kth bit is set if the kth type of block is a possibility. Then, we create a transition map T[state1][state2] -> state that takes a left state and a right state and outputs all possible parent states.
At the end, applying these transitions is straightforward. However, this approach is not correct, because the transitions are not independent. If for example we have states in a row A, {B or C}, A, and allowed triples (A, B, D)(C, A, D), then regardless of the choice of {B or C} we cannot create the next row of the pyramid.

  public boolean pyramidTransition(String bottom, List<String> allowed) {
    int[][] T = new int[1 << 7][1 << 7];
    for (String triple : allowed) {
      int u = 1 << (triple.charAt(0) - 'A');
      int v = 1 << (triple.charAt(1) - 'A');
      int w = 1 << (triple.charAt(2) - 'A');
      for (int b1 = 0; b1 < (1 << 7); ++b1)
        if ((u & b1) > 0)
          for (int b2 = 0; b2 < (1 << 7); ++b2)
            if ((v & b2) > 0)
              T[b1][b2] |= w;
    }

    int[] state = new int[bottom.length()];
    int t = 0;
    for (char c : bottom.toCharArray())
      state[t++] = 1 << (c - 'A');
    while (t-- > 1)
      for (int i = 0; i < t; ++i)
        state[i] = T[state[i]][state[i + 1]];
    return state[0] > 0;
  }
https://leetcode.com/problems/pyramid-transition-matrix/discuss/113037/counter-example-to-the-standard-code
For the following example:
"ABCD"
["BCE","BCF","ABA","CDA","AEG","FAG","GGG"]
Should we output false (if I am interpreting the problem correctly)?
But the standard code outputs true. Could anyone explain this?

Since the DP method considered the characters independent from the lower layer. A character can be used only if it's based on certain character pairs, however in the DP method if a character can be used based on a pair, it will be marked as true, and it will be used for other pairs even if it's not allowed

这是一种DP的解法,建立一个三维的dp数组,其中dp[i][j][ch]表示在金字塔(i, j)位置上是否可以放字符ch,金字塔的宽和高已经确定了,都是n。每个位置对应着nxn的数组的左半边,如下所示:
F _ _
D E _
A B C
除了底层,每个位置可能可以放多个字符,所以这里dp数组是一个三维数组,第三维的长度为7,因为题目中限定了字母只有A到G共7个,如果dp值为true,表示该位置放该字母,我们根据bottom字符串来初始化dp数组的底层。这里还是需要一个HashMap,不过跟上面的解法略有不同的是,我们建立上方字母跟其能放的基座字符串集合的映射,因为一个字母可能可以放多个位置,所以用个集合来表示。然后我们就开始从倒数第二层开始往顶部更新啦,对于金字塔的每个位置,我们都遍历A到G中所有的字母,如果当前字母在HashMap中有映射,则我们遍历对应的基座字符串集合中的所有字符串,基座字符串共有两个字母,左边的字母对应的金字塔中的位置是(i + 1, j),右边的字母对应的位置是(i + 1, j + 1),我们只要在这两个位置上分别查询对应的字母的dp值是否为true,是的话,说明当前位置有字母可以放,我们将当前位置的字母对应的dp值赋值为true。这样,当我们整个更新完成了之后,我们只要看金字塔顶端位置(0, 0)是否有字母可以放,有的话,说明可以搭出金字塔,返回true,否则返回false
https://leetcode.com/problems/pyramid-transition-matrix/discuss/113075/DP-O(n2-*-m)
n is the size of bottomm is the length of allowed.
Update: even this solution is ACed, personally, I don't think it is correct - see https://discuss.leetcode.com/topic/115541/counter-example-to-the-standard-code
But, I still think it's worth to note it down here to help understand what the official solution wanted it be.
    public boolean pyramidTransition(String bottom, List<String> allowed) {
        int n = bottom.length();
        Map<Character, List<String>> map = new HashMap<>();
        for(String s : allowed) {
            char key = s.charAt(2);
            if (!map.containsKey(key))
                map.put(key, new ArrayList<>());
            map.get(key).add(s.substring(0,2));
        }
        
        boolean[][][] dp = new boolean[n][n][7];
        for(int i = 0; i < n; i++) {
            dp[n-1][i][bottom.charAt(i)-'A'] = true;
        }
        for(int i = n-2; i >= 0; i--) {
            for(int j = 0; j <= i; j++)
                for(char ch = 'A'; ch <= 'G'; ch++) {
                    if (!map.containsKey(ch)) continue;
                    for(String b : map.get(ch)) {
                        if (dp[i+1][j][b.charAt(0) - 'A'] && dp[i+1][j+1][b.charAt(1)-'A'])
                            dp[i][j][ch - 'A'] = true;
                    }
                }
        }
        
        for(int i = 0; i < 7; i++)
            if (dp[0][0][i]) return true;
        return false;
    }
https://blog.csdn.net/u014688145/article/details/78951010
注意allowed中的三元组是可以重复利用的,这样我们定义dp:

dp[i][j][k]: 表示第i层上,第j个元素为k
1
根据bottom,可以初始化每个位置j上含有的字符bottom[j], dp更新式如下:

dp[i][j][k] = true if dp[i + 1][j][l] = true && dp[i + 1][j + 1][r] = true && lrk组成的字符串在allowed中出现过。

  public boolean pyramidTransition(String bottom, List<String> allowed) {
    Map<String, List<String>> mem = new HashMap<>();
    boolean[][] dp = new boolean[20][7];
    int n = bottom.length();

    for (String allow : allowed) {
      mem.computeIfAbsent(allow.substring(0, 2), k -> new ArrayList<>()).add(allow.substring(2));
    }

    for (int i = 0; i < n; ++i) {
      dp[i][bottom.charAt(i) - 'A'] = true;
    }

    for (int i = n - 1; i >= 1; --i) {
      boolean[][] ndp = new boolean[20][7];
      for (int j = 0; j < i; ++j) {
        for (int l = 0; l < 7; ++l) {
          for (int r = 0; r < 7; ++r) {
            if (dp[j][l] && dp[j + 1][r]) {
              if (mem.containsKey((char) (l + 'A') + "" + (char) (r + 'A'))) {
                for (String s : mem.get((char) (l + 'A') + "" + (char) (r + 'A'))) {
                  ndp[j][s.charAt(0) - 'A'] = true;
                }
              }
            }
          }
        }
      }
      dp = ndp;
    }

    for (int i = 0; i < 7; ++i) {
      if (dp[0][i])
        return true;
    }
    return false;

  }


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