2015年9月18日星期五

Lintcode: Topological Sorting

Given an directed graph, a topological order of the graph nodes is defined as follow:
  • For each directed edge A -> B in graph, A must before B in the order list.
  • The first node in the order can be any node in the graph with no nodes direct to it.
Find any topological order for the given graph.
Have you met this question in a real interview? 
Yes
Example
For graph as follow:
picture
The topological order can be:
[0, 1, 2, 3, 4, 5]
[0, 2, 3, 1, 5, 4]
...
Note
You can assume that there is at least one topological order in the graph.
Challenge
Can you do it in both BFS and DFS?
Tags Expand 

九章算法DFS
//both BFS and DFS
http://algorithm.yuanbin.me/zh-cn/graph/topological_sorting.html
//good BFS version
http://meetqun.com/thread-5526-1-1.html


Topological sort is for DAG(Directed acyclic graph)

indgree makes sure the topological order and vertices will not be counted repeatedly.

BFS solution:
s1: calc indegree of all vertices
s2: get the origin(vertice with 0 indegree) and push it into queue
s3: While queue is not empty:
          pop the front element as cur and push it into result vector
          for cur adjacent vertices:
                  minus its indegree by 1;
                  if its indegree equals to 0, push this vertice to result vector

Time: O(V+E)
s1-- O(V+E)
s2-- O(V)
s3-- O(V+E)
Space:O(V)


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/**
 * Definition for Directed graph.
 * struct DirectedGraphNode {
 *     int label;
 *     vector<DirectedGraphNode *> neighbors;
 *     DirectedGraphNode(int x) : label(x) {};
 * };
 */
class Solution {
public:
    /**
     * @param graph: A list of Directed graph node
     * @return: Any topological order for the given graph.
     */
    vector<DirectedGraphNode*> topSort(vector<DirectedGraphNode*> graph) {
        // write your code here
        //look for the head node
        vector<DirectedGraphNode*> res;
        if(!graph.size()) return res;
        //get indegree    
        unordered_map<DirectedGraphNode*, int> indegree;
        indeg(graph, indegree);
        //push nodes with 0 indegree and pop to result;
        queue<DirectedGraphNode*> q;
        bfs(graph, indegree, q, res);
        return res;
    }
private:
    void indeg(vector<DirectedGraphNode*> &graph, unordered_map<DirectedGraphNode*, int> &indegree){
        for(int i = 0; i < graph.size(); i++){
            for(int j = 0; j < graph[i]->neighbors.size(); j++){
                if(!indegree.count(graph[i]->neighbors[j])) indegree[graph[i]->neighbors[j]] = 1;
                else indegree[graph[i]->neighbors[j]]++;
            }
        }
    }
    void bfs(vector<DirectedGraphNode*> &graph, unordered_map<DirectedGraphNode*, int> &indegree, queue<DirectedGraphNode*> &q, vector<DirectedGraphNode*> &res){
        for(int i = 0; i < graph.size(); i++){
            if(indegree[graph[i]] == 0) {
                q.push(graph[i]);
                //res.push_back(graph[i]);
            }
        }
        while(!q.empty()){
            DirectedGraphNode* cur = q.front();
            res.push_back(cur);
            q.pop();
            for(int i = 0; i < cur->neighbors.size(); i++){
                indegree[cur->neighbors[i]]--;
                if(indegree[cur->neighbors[i]] == 0) q.push(cur->neighbors[i]);
            }
        }
    }
};

DFS solution 1:
Not real DFS, actually just like BFS, use stack replace the queue in BFS solution
s1: calc indegree of all vertices
s2: DFS the vertice with 0 indegree
s3: DFS( minus adjacent vertices' indegrees by 1, if any vertice indegree is 0, bfs this vertice)

O(V+E)


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/**
 * Definition for Directed graph.
 * struct DirectedGraphNode {
 *     int label;
 *     vector<DirectedGraphNode *> neighbors;
 *     DirectedGraphNode(int x) : label(x) {};
 * };
 */
class Solution {
public:
    /**
     * @param graph: A list of Directed graph node
     * @return: Any topological order for the given graph.
     */
    vector<DirectedGraphNode*> topSort(vector<DirectedGraphNode*> graph) {
        // write your code here
        //look for the head node
        vector<DirectedGraphNode*> res;
        if(!graph.size()) return res;
        //get indegree    
        unordered_map<DirectedGraphNode*, int> indegree;
        indeg(graph, indegree);
        //push nodes with 0 indegree and pop to result;
        for(int i = 0; i < graph.size(); i++){
            if(indegree[graph[i]] == 0) DFS(indegree, graph[i], res);
        }
        return res;
    }
private:
    void indeg(vector<DirectedGraphNode*> &graph, unordered_map<DirectedGraphNode*, int> &indegree){
        for(int i = 0; i < graph.size(); i++){
            for(int j = 0; j < graph[i]->neighbors.size(); j++){
                /*if(!indegree.count(graph[i]->neighbors[j])) indegree[graph[i]->neighbors[j]] = 1;
                else indegree[graph[i]->neighbors[j]]++;*/
                indegree[graph[i]->neighbors[j]]++;
            }
        }
    }
    void DFS(unordered_map<DirectedGraphNode*, int> &indegree, DirectedGraphNode* node, vector<DirectedGraphNode*>& res){
        indegree[node]--;
        res.push_back(node);
        for(int i = 0; i < node->neighbors.size(); i++){
            indegree[node->neighbors[i]]--;
            if(indegree[node->neighbors[i]] == 0) DFS(indegree, node->neighbors[i], res);
        }
    }
};

DFS solution 2:
Used a stack to record DFS order and pint the stack
In DFS, we push current node in stack in the end

a vertex is pushed to stack only when all of its adjacent vertices (and their adjacent vertices and so on) are already in stack.

//thought reference:
http://www.geeksforgeeks.org/topological-sorting/
//thought / process /codes reference
https://www.youtube.com/watch?v=jksMzq4LgfM


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/**
 * Definition for Directed graph.
 * struct DirectedGraphNode {
 *     int label;
 *     vector<DirectedGraphNode *> neighbors;
 *     DirectedGraphNode(int x) : label(x) {};
 * };
 */
class Solution {
public:
    /**
     * @param graph: A list of Directed graph node
     * @return: Any topological order for the given graph.
     */
    vector<DirectedGraphNode*> topSort(vector<DirectedGraphNode*> graph) {
        // write your code here
        //look for the head node
        vector<DirectedGraphNode*> res;
        if(!graph.size()) return res;
        //get indegree    
        unordered_map<DirectedGraphNode*, int> indegree;
        indeg(graph, indegree);
        //push nodes with 0 indegree and pop to result;
        unordered_set<DirectedGraphNode*> mark;
        stack<DirectedGraphNode*> s;
        for(int i = 0; i < graph.size(); i++){
            if(indegree[graph[i]] == 0) DFS(mark, graph[i], s);
        }
        while(!s.empty()){
            res.push_back(s.top());
            s.pop();
        }
        return res;
    }
private:
    void indeg(vector<DirectedGraphNode*> &graph, unordered_map<DirectedGraphNode*, int> &indegree){
        for(int i = 0; i < graph.size(); i++){
            for(int j = 0; j < graph[i]->neighbors.size(); j++){
                /*if(!indegree.count(graph[i]->neighbors[j])) indegree[graph[i]->neighbors[j]] = 1;
                else indegree[graph[i]->neighbors[j]]++;*/
                indegree[graph[i]->neighbors[j]]++;
            }
        }
    }
    void DFS(unordered_set<DirectedGraphNode*> &mark, DirectedGraphNode* node, stack<DirectedGraphNode*> &s){
        mark.insert(node);
        for(int i = 0; i < node->neighbors.size(); i++){
            if(!mark.count(node->neighbors[i])) DFS(mark, node->neighbors[i], s);
        }
        s.push(node);
    }
};


Lintcode second:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/**
 * Definition for Directed graph.
 * struct DirectedGraphNode {
 *     int label;
 *     vector<DirectedGraphNode *> neighbors;
 *     DirectedGraphNode(int x) : label(x) {};
 * };
 */
class Solution {
public:
    /**
     * @param graph: A list of Directed graph node
     * @return: Any topological order for the given graph.
     */
    vector<DirectedGraphNode*> topSort(vector<DirectedGraphNode*> graph) {
        // write your code here
        //get indegrees
        unordered_map<DirectedGraphNode*, int> indegrees;
        for(int i = 0; i < graph.size(); i++){
            for(int j = 0; j < graph[i]->neighbors.size(); j++){
                indegrees[graph[i]->neighbors[j]]++;
            }
        }
        //get head
        queue<DirectedGraphNode*> q;
        for(int i = 0; i < graph.size(); i++){
            if(indegrees[graph[i] ] == 0) q.push(graph[i]);
        }
        //start sort
        vector<DirectedGraphNode*> res;
        while(!q.empty()){
            DirectedGraphNode* cur = q.front();
            res.push_back(cur);
            q.pop();
            for(int i = 0; i < cur->neighbors.size(); i++){
                indegrees[cur->neighbors[i]]--;
                if(indegrees[cur->neighbors[i]] == 0) q.push(cur->neighbors[i]);
            }
        }
        return res;
    }
};

没有评论:

发表评论