LeetCode 261 - Graph Valid Tree


http://www.elvisyu.com/graph-valid-tree-union-and-find/
Given n nodes labeled from 0 to n – 1 and a list of undirected edges (each edge is a pair of nodes), write a function to check whether these edges make up a valid tree.
For example:
Given n = 5 and edges = [[0, 1], [0, 2], [0, 3], [1, 4]], return true.
Given n = 5 and edges = [[0, 1], [1, 2], [2, 3], [1, 3], [1, 4]], return false.
Hint:
Given n = 5 and edges = [[0, 1], [1, 2], [3, 4]], what should your return? Is this case a valid tree?
According to the definition of tree on Wikipedia: “a tree is an undirected graph in which any two vertices are connected by exactly one path. In other words, any connected graph without simple cycles is a tree.”
鉴定一个图是否是一个有效的树,既没有回路。
图类的题目基本上都可以用DFS和BFS来解决,这题也不例外。同时,Union and Find- 并查集也可以很好的解决这个问题。
1. DFS
由于是无向图,所以根据给定的edges我们需要造一个双向的图,用List<List<Integer>>即可实现,同时维护一个已访问数组。在深度遍历图的时候,如果当前节点已访问过,则表示存在回路。
public boolean validTree(int n, int[][] edges) {
        // initialize adjacency list
        List<List<Integer>> adjList = new ArrayList<List<Integer>>(n);
        // initialize vertices
        for (int i = 0; i < n; i++)
            adjList.add(i, new ArrayList<Integer>());
        // add edges    
        for (int i = 0; i < edges.length; i++) {
            int u = edges[i][0], v = edges[i][1];
            adjList.get(u).add(v);
            adjList.get(v).add(u);
        }
        boolean[] visited = new boolean[n];
        // make sure there's no cycle
        if (hasCycle(adjList, 0, visited, -1))
            return false;
        // make sure all vertices are connected
        for (int i = 0; i < n; i++) {
            if (!visited[i])
                return false;
        }
        return true;
    }
    // check if an undirected graph has cycle started from vertex u
    boolean hasCycle(List<List<Integer>> adjList, int u, boolean[] visited, int parent) {
        visited[u] = true;
        for (int i = 0; i < adjList.get(u).size(); i++) {
            int v = adjList.get(u).get(i);
            //如果是临近的父节点,则跳过。
            if ((visited[v] && parent != v) || (!visited[v] && hasCycle(adjList, v, visited, u)))
                return true;
        }
        return false;
    }
http://buttercola.blogspot.com/2015/08/leetcode-graph-valid-tree.html
    public boolean validTree(int n, int[][] edges) {
         
        // Create an adj list
        List<List<Integer>> adjList = new ArrayList<List<Integer>>();
        for (int i = 0; i < n; i++) {
            adjList.add(new ArrayList<Integer>());
        }
         
        for (int[] edge : edges) {
            adjList.get(edge[1]).add(edge[0]);
            adjList.get(edge[0]).add(edge[1]);
        }
         
        boolean[] visited = new boolean[n];
         
        if (!validTreeHelper(n, edges, 0, -1, visited, adjList)) {
            return false;
        }
         
        // Check the islands
        for (boolean v : visited) {
            if (!v) {
                return false;
            }
        }
         
        return true;
    }
     
    private boolean validTreeHelper(int n, int[][] edges, int vertexId, int parentId,
                                    boolean[] visited, List<List<Integer>> adjList) {
        if (visited[vertexId]) {
            return false;
        }
         
        visited[vertexId] = true;
         
        List<Integer> neighbors = adjList.get(vertexId);
        for (Integer neighbor : neighbors) {
            if (neighbor != parentId && !validTreeHelper(n, edges, neighbor, vertexId, visited, adjList)) {
                return false;
            }
        }
         
        return true;
    }
X.BFS
若一个无向图是一棵树,则其需要满足两个条件:
  1. # nodes = # edges + 1
  2. 不成环
第一个条件很好判断,比较节点数和边数就可以了。重点就在判断是否存在环了。我们可以发现,在满足第一个条件后,若图中存在环,则图中至少存在两个连通块,这意味着我们从任意一个节点出发开始遍历,最后都必然无法遍历整个图。因此只需要任选一个节点出发遍历,若最后遍历得到的联通图中的节点数目小于图中节点总数目,图中就存在环了
    public boolean validTree(int n, int[][] edges) {
         
        // Create an adj list
        List<List<Integer>> adjList = new ArrayList<List<Integer>>();
        for (int i = 0; i < n; i++) {
            adjList.add(new ArrayList<Integer>());
        }
         
        for (int[] edge : edges) {
            adjList.get(edge[1]).add(edge[0]);
            adjList.get(edge[0]).add(edge[1]);
        }
         
        boolean[] visited = new boolean[n];
         
        Queue<Integer> queue = new LinkedList<Integer>();
        queue.offer(0);
         
        while (!queue.isEmpty()) {
            int vertexId = queue.poll();
             
            if (visited[vertexId]) {
                return false;
            }
             
            visited[vertexId] = true;
             
            for (int neighbor : adjList.get(vertexId)) {
                if (!visited[neighbor]) {
                    queue.offer(neighbor);
                }
            }
        }
         
        // Check the islands
        for (boolean v : visited) {
            if (!v) {
                return false;
            }
        }
         
        return true;
    }
https://leetcode.com/discuss/54211/ac-java-solutions-union-find-bfs-dfs
// BFS, using queue private boolean valid(int n, int[][] edges) { // build the graph using adjacent list List<Set<Integer>> graph = new ArrayList<Set<Integer>>(); for(int i = 0; i < n; i++) graph.add(new HashSet<Integer>()); for(int[] edge : edges) { graph.get(edge[0]).add(edge[1]); graph.get(edge[1]).add(edge[0]); } // no cycle boolean[] visited = new boolean[n]; Queue<Integer> queue = new ArrayDeque<Integer>(); queue.add(0); while(!queue.isEmpty()) { int node = queue.poll(); if(visited[node]) return false; visited[node] = true; for(int neighbor : graph.get(node)) { queue.offer(neighbor); graph.get(neighbor).remove((Integer)node); } } // fully connected for(boolean result : visited) { if(!result) return false; } return true; }
In the BFS one, while loop can't not detect loop, try{ [1, 2] [2, 3] [1, 3]}:
boolean[] visited = new boolean[n];
        Queue<Integer> queue = new ArrayDeque<Integer>();
        queue.add(0);
        while(!queue.isEmpty())
        {
            int node = queue.poll();
            if(visited[node])
                return false;
            visited[node] = true;
            for(int neighbor : graph.get(node))
            {
                queue.offer(neighbor);
                graph.get(neighbor).remove((Integer)node);
            }
        }
Should be:
boolean[] visited = new boolean[n];
        Queue<Integer> queue = new ArrayDeque<Integer>();
        queue.add(0);
        while(!queue.isEmpty())
        {
            int node = queue.poll();
            for(int neighbor : graph.get(node))
            {
                if(visited[neighbor])
                    return false;
                visited[neighbor] = true;                
                queue.offer(neighbor);
                graph.get(neighbor).remove((Integer)node);
            }
        }
https://leetcode.com/discuss/52555/java-bfs-solution
public boolean validTree(int n, int[][] edges) { // n must be at least 1 if (n < 1) return false; // create hashmap to store info of edges Map<Integer, Set<Integer>> map = new HashMap<>(); for (int i = 0; i < n; i++) map.put(i, new HashSet<>()); for (int[] edge : edges) { map.get(edge[0]).add(edge[1]); map.get(edge[1]).add(edge[0]); } // bfs starts with node in label "0" Set<Integer> set = new HashSet<>(); Queue<Integer> queue = new LinkedList<>(); queue.add(0); while (!queue.isEmpty()) { int top = queue.remove(); // if set already contains top, then the graph has cycle // hence return false if (set.contains(top)) return false; for (int node : map.get(top)) { queue.add(node); // we should remove the edge: node -> top // after adding a node into set to avoid duplicate // since we already consider top -> node map.get(node).remove(top); } set.add(top); } return set.size() == n; }
X. 并查集 Union-Find
https://discuss.leetcode.com/topic/21712/ac-java-union-find-solution
let's say the graph has V vertices and E edges, the find( ) function takes O(V) time because in the worst case it has to go through all the vertices, and from outside we loop through all the edges, so the time complexity should be O(V*E).
    public boolean validTree(int n, int[][] edges) {
        // initialize n isolated islands
        int[] nums = new int[n];
        Arrays.fill(nums, -1);
        
        // perform union find
        for (int i = 0; i < edges.length; i++) {
            int x = find(nums, edges[i][0]);
            int y = find(nums, edges[i][1]);
            
            // if two vertices happen to be in the same set
            // then there's a cycle
            if (x == y) return false;
            
            // union
            nums[x] = y;
        }
        
        return edges.length == n - 1;
    }
    
    int find(int nums[], int i) {
        if (nums[i] == -1) return i;
        return find(nums, nums[i]);
    }
https://segmentfault.com/a/1190000003791051
就是先构建一个数组,节点0到节点n-1,刚开始都各自独立的属于自己的集合。这时集合的编号是节点号。然后,每次union操作时,我们把整个并查集中,所有和第一个节点所属集合号相同的节点的集合号,都改成第二个节点的集合号。这样就将一个集合的节点归属到同一个集合号下了。我们遍历一遍输入,把所有边加入我们的并查集中,加的同时判断是否有环路。最后如果并查集中只有一个集合,则说明可以构建树。
    public boolean validTree(int n, int[][] edges) {
        UnionFind uf = new UnionFind(n);
        for(int i = 0; i < edges.length; i++){
            // 如果两个节点已经在同一集合中,说明新的边将产生环路
            if(!uf.union(edges[i][0], edges[i][1])){
                return false;
            }
        }
        return uf.count() == 1;
    }
    
    public class UnionFind {
        
        int[] ids;
        int cnt;
        
        public UnionFind(int size){
            this.ids = new int[size];
            //初始化并查集,每个节点对应自己的集合号
            for(int i = 0; i < this.ids.length; i++){
                this.ids[i] = i;
            }
            this.cnt = size;
        }
        public boolean union(int m, int n){
            int src = find(m);
            int dst = find(n);
            //如果两个节点不在同一集合中,将两个集合合并为一个
            if(src != dst){
                for(int i = 0; i < ids.length; i++){
                    if(ids[i] == src){
                        ids[i] = dst;
                    }
                }
                // 合并完集合后,集合数减一
                cnt--;
                return true;
            } else {
                return false;
            }
        }
        public int find(int m){
            return ids[m];
        }
        public boolean areConnected(int m, int n){
            return find(m) == find(n);
        }
        public int count(){
            return cnt;
        }
    }

X. Union and Find。
先附上一个很经典的图。 并查集可以很简单的查询到一个图的联通情况,或者返回最少路径数。


其中,队列toCheck中记录的是那些我们已经访问过但尚未处理其相连节点的节点。
并查集的基本操作有两个:
  1. find - 找到当前连通块的根节点
  2. connect - 连接两个连通块

当一条边会将已经属于同一连通块的两个节点连接起来时,图中就存在了环。
bool validTree(int n, vector<vector<int>>& edges) {
if (n != edges.size() + 1) {
return false;
}
vector<int> root(n, -1);
for (auto& edge : edges) {
int root_a = find(edge[0], root);
int root_b = find(edge[1], root);
if (root_a == root_b) {
return false;
}
// connect
root[root_a] = root_b;
}
return true;
}
int find(int a, vector<int>& root) {
if (root[a] == -1) {
return a;
}
return root[a] = find(root[a], root);
}


public boolean validTree(int n, int[][] edges) {
        // initialize n isolated islands
        int[] nums = new int[n];
        Arrays.fill(nums, -1);
        // perform union find
        for (int i = 0; i < edges.length; i++) {
            int x = find(nums, edges[i][0]);
            int y = find(nums, edges[i][1]);
            // if two vertices happen to be in the same set
            // then there's a cycle
            if (x == y) return false;
            // union
            nums[x] = y;
        }
        return edges.length == n - 1;
    }
    int find(int nums[], int i) {
        if (nums[i] == -1) return i;
        //反复寻找父节点。
        return find(nums, nums[i]);
    }
http://likesky3.iteye.com/blog/2240154
  1.     int count = 0;  
  2.     int[] id = null;  
  3.     int[] size = null;  
  4.     public boolean validTree(int n, int[][] edges) {  
  5.         initUnionFind(n);  
  6.         for (int i = 0; i < edges.length; i++) {  
  7.             int p = edges[i][0], q = edges[i][1];  
  8.             if (find(p) == find(q))  
  9.                 return false;  
  10.             union(p, q);  
  11.         }  
  12.         return count == 1 ? true : false;  
  13.     }  
  14.     public void initUnionFind(int n) {  
  15.         id = new int[n];  
  16.         size = new int[n];  
  17.         for (int i = 0; i < n; i++) {  
  18.             id[i] = i;  
  19.             size[i] = 1;  
  20.         }  
  21.         count = n;  
  22.     }  
  23.     //version 4: weighted quick union with path compression, find & union, very close to O(1)  
  24.     public int find(int p) {  
  25.         while (p != id[p]) {  
  26.             id[p] = id[id[p]];  
  27.             p = id[p];  
  28.         }  
  29.         return p;  
  30.     }  
  31.     public void union(int p, int q) { //same with version 3  
  32.         int pRoot = find(p), qRoot = find(q);  
  33.         if (size[pRoot] < size[qRoot]) {  
  34.             id[pRoot] = qRoot;  
  35.             size[qRoot] += size[pRoot];  
  36.         } else {  
  37.             id[qRoot] = pRoot;  
  38.             size[pRoot] += size[qRoot];  
  39.         }  
  40.         count--;  
  41.     }  
  42.     //version 3: weighted quick union, find & union, O(logn)  
  43.     public int find3(int p) { // same with version 2  
  44.         while (p != id[p]) p = id[p];  
  45.         return p;  
  46.     }  
  47.     public void union3(int p, int q) {  
  48.         int pRoot = find(p), qRoot = find(q);  
  49.         if (size[pRoot] < size[qRoot]) {  
  50.             id[pRoot] = qRoot;  
  51.             size[qRoot] += size[pRoot];  
  52.         } else {  
  53.             id[qRoot] = pRoot;  
  54.             size[pRoot] += size[qRoot];  
  55.         }  
  56.         count--;  
  57.     }  
  58.     // version 2: quick union, find & union, O(tree height)  
  59.     public int find2(int p) {  
  60.         while (p != id[p]) p = id[p];  
  61.         return p;  
  62.     }  
  63.     public void union2(int p, int q) {  
  64.         int pRoot = find(p), qRoot = find(q);  
  65.         id[pRoot] = qRoot;  
  66.         count--;  
  67.     }  
  68.     // version 1: quick find, find O(1), union O(n)  
  69.     public int find1(int p) {  
  70.         return id[p];  
  71.     }  
  72.     public void union1(int p, int q) {  
  73.         int pId = find(p), qId = find(q);// 特别注意进入循环先保存原始值,循环过程id[p]会被更改  
  74.         for (int i = 0; i < id.length; i++) {  
  75.             if (id[i] == pId)  
  76.                 id[i] = qId;  
  77.         }  
  78.         count--;  
  79.     } 
  1.     // union by rank  
  2.     public boolean union(int p, int q) {  
  3.         int pRoot = find(p), qRoot = find(q);  
  4.         if (pRoot == qRoot)  
  5.             return false;  
  6.         if (s[pRoot] < s[qRoot]) {  
  7.             s[qRoot] = pRoot;  
  8.         } else {  
  9.             if (s[pRoot] == s[qRoot])  
  10.                 s[qRoot]--;  
  11.             s[pRoot] = qRoot;  
  12.         }  
  13.         return true;  
  14.     }  
  15.     // union by size  
  16.     public boolean union1(int p, int q) {  
  17.         int pRoot = find(p), qRoot = find(q);  
  18.         if (pRoot == qRoot)  
  19.             return false;  
  20.         if (s[pRoot] < s[qRoot]) {  
  21.             s[pRoot] += s[qRoot];  
  22.             s[qRoot] = pRoot;  
  23.         } else {  
  24.             s[qRoot] += s[pRoot];  
  25.             s[pRoot] = qRoot;  
  26.         }  
  27.         return true;  
  28.     } 
http://www.jiuzhang.com/solutions/graph-valid-tree/
      class UnionFind{
        HashMap<Integer, Integer> father = new HashMap<Integer, Integer>();
        UnionFind(int n){
            for(int i = 0 ; i < n; i++) {
                father.put(i, i); 
            }
        }
        int compressed_find(int x){
            int parent =  father.get(x);
            while(parent!=father.get(parent)) {
                parent = father.get(parent);
            }
            int temp = -1;
            int fa = father.get(x);
            while(fa!=father.get(fa)) {
                temp = father.get(fa);
                father.put(fa, parent) ;
                fa = temp;
            }
            return parent;
                
        }
        
        void union(int x, int y){
            int fa_x = compressed_find(x);
            int fa_y = compressed_find(y);
            if(fa_x != fa_y)
                father.put(fa_x, fa_y);
        }
    }
    public boolean validTree(int n, int[][] edges) {
        // tree should have n nodes with n-1 edges
        if (n - 1 != edges.length) {
            return false;
        }
        
        UnionFind uf = new UnionFind(n);
        
        for (int i = 0; i < edges.length; i++) {
            if (uf.compressed_find(edges[i][0]) == uf.compressed_find(edges[i][1])) {
                return false;
            }
            uf.union(edges[i][0], edges[i][1]);
        }
        return true;
    }

并查集可以解决的问题很多,比如:
Example1:
在某个城市里住着n个人,任何两个认识的人不是朋友就是敌人,而且满足:
n    我朋友的朋友是我的朋友;
n    我敌人的敌人是我的朋友;
已知关于 n个人的m条信息(即某2个人是朋友或者敌人),假设所有是朋友的人一定属于同一个团伙,请计算该城市最多有多少团伙?
         分析:要知道有多少个团伙,就要知道每个人属于哪个团伙?还有做到的是若A属于Team1同时也属于Team2那么就要合并Team1和Team2。这就是并查集的“并”和“查”了。显然天生就要用到并查集解决这个题了。

Example2:
某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路?请给出一个可行的规划。
Input
测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M;随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1到N编号。
注意:两个城市之间可以有多条道路相通,也就是说
3 3
1 2
1 2
2 1
这种输入也是合法的
当N为0时,输入结束,该用例不被处理。
Output
对每个测试用例,在1行里输出最少还需要建设的道路数目。
http://blog.hyoung.me/cn/2017/03/breadth-first-search/


Read full article from LIKE CODING: LeetCode [261] Graph Valid Tree

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