Data Structure: 图的拓扑排序

Course Schedule

There are a total of n courses you have to take, labeled from 0 to n - 1.
Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]
Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?
For example:
2, [[1,0]]
There are a total of 2 courses to take. To take course 1 you should have finished course 0. So it is possible.
2, [[1,0],[0,1]]
There are a total of 2 courses to take. To take course 1 you should have finished course 0, and to take course 0 you should also have finished course 1. So it is impossible.

 

class Solution {
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        // special cases
        if (numCourses <= 1) {
            return true;
        }
        
        if (prerequisites == null || prerequisites.length == 0
            || prerequisites[0] == null || prerequisites[0].length == 0) {
            return true;
        }
        
        // transfer the edges list to adjacent list
        Map<Integer, Set<Integer>> adjacentList = new HashMap<>();
        
        // Initialize the adjacent list
        for (int i = 0; i < numCourses; ++i) {
            adjacentList.put(i, new HashSet<Integer>());
        }
        // Assign the adjacent list
        int n = prerequisites.length; 
        for (int j = 0; j < n; ++j) {
            adjacentList.get(prerequisites[j][0]).add(prerequisites[j][1]);
        }
        
        // 把不需要前修课程要求的课拿出来先
        int courseCount = numCourses;
        Queue<Integer> canAccessCourses = new LinkedList<>();
        
        for (Integer course : adjacentList.keySet()) {
            if (adjacentList.get(course).isEmpty()) {
                canAccessCourses.offer(course);
                --courseCount;
            }
        }
        
        // 利用这些不需要先修的课程,试着去修它们作为先修课的课程,进行BFS,每一门can access的,就把把这门课当做先修课的课程的先修要求中,移除
        // 这门课。如果移除后,那门课也能修了,就将其加入can access的队列中。
        while (canAccessCourses.isEmpty() == false) {
            Integer cur = canAccessCourses.poll();
            for (Integer course : adjacentList.keySet()) {
                Set<Integer> tmp = adjacentList.get(course);
                if (tmp.contains(cur)) {
                    tmp.remove(cur);
                    if (tmp.isEmpty()) {
                        canAccessCourses.offer(course);
                        --courseCount;
                    }
                }
            }
        }
        return courseCount == 0;
    }
}

 

1203. Sort Items by Groups Respecting Dependencies

There are n items each belonging to zero or one of m groups where group[i] is the group that the i-th item belongs to and it's equal to -1 if the i-th item belongs to no group. The items and the groups are zero indexed. A group can have no item belonging to it.

Return a sorted list of the items such that:

  • The items that belong to the same group are next to each other in the sorted list.
  • There are some relations between these items where beforeItems[i] is a list containing all the items that should come before the i-th item in the sorted array (to the left of the i-th item).

Return any solution if there is more than one solution and return an empty list if there is no solution.

Example 1:

Input: n = 8, m = 2, group = [-1,-1,1,0,0,1,0,-1], beforeItems = [[],[6],[5],[6],[3,6],[],[],[]]
Output: [6,3,4,1,5,2,0,7]

Example 2:

Input: n = 8, m = 2, group = [-1,-1,1,0,0,1,0,-1], beforeItems = [[],[6],[5],[6],[3],[],[4],[]]
Output: []
Explanation: This is the same as example 1 except that 4 needs to be before 6 in the sorted list.

Constraints:

  • 1 <= m <= n <= 3*10^4
  • group.length == beforeItems.length == n
  • -1 <= group[i] <= m-1
  • 0 <= beforeItems[i].length <= n-1
  • 0 <= beforeItems[i][j] <= n-1
  • i != beforeItems[i][j]
  • beforeItems[i] does not contain duplicates elements.

 

这道题加入了in_degree作为topo sort的参考后,速度比只用一个set要快,不会超时。因为不用每次都通过find。注意这里的in_degree是from到to,to的indegree加1. From是before_requisite. 

 

 

class Graph {
    unordered_map<int, vector<int>> adj;
    unordered_map<int, int> indegree;
public:
    Graph() {}
    
    Graph(int n) {
        adj = unordered_map<int, vector<int>>{};
        indegree = unordered_map<int, int>{};
        for (int i = 0; i < n; ++i) {
            indegree[i] = 0;
            adj[i] = vector<int>{};
        }
    }
    
    Graph(vector<int> &vec) {
        adj = unordered_map<int, vector<int>>{};
        indegree = unordered_map<int, int>{};
        for (const int &i : vec) {
            indegree[i] = 0;
            adj[i] = vector<int>{};
        }
    }
    
    void addEdge(int from, int to) {
        adj[from].push_back(to);
        indegree[to]++;
    }
    
    vector<int> sort() {
        queue<int> q;
        vector<int> ans;
        for (const auto &p : indegree) {
            if (p.second == 0) q.push(p.first);
        }
        
        while (!q.empty()) {
            int h = q.front();
            q.pop();
            ans.push_back(h);
            for (const auto &i : adj[h]) {
                indegree[i]--;
                if (indegree[i] == 0) q.push(i);
            }
        }
        
        return ans;
    }
};

class Solution {
public:
    vector<int> sortItems(int n, int m, vector<int>& group, vector<vector<int>>& beforeItems) {
        // build two level of graph. 
        vector<vector<int>> group_and_elements(m, vector<int>(0));
        for (int element = 0; element < n; ++element) {
            if (group.at(element) == -1) {
                vector<int> tmp(1, element);
                group_and_elements.push_back(tmp);
                group[element] = group_and_elements.size() - 1;
                continue;
            }
            group_and_elements.at(group.at(element)).push_back(element);
        }
        
        // build a graph in which different nodes represent different groups. 
        Graph group_graph(group_and_elements.size());
        vector<Graph> group_element_graphs;
        for (auto elements_with_same_group : group_and_elements) {
            // build another graph in which different nodes represent different elements within the same group.
            group_element_graphs.push_back(Graph(elements_with_same_group));
        }
        
        for (int element_index = 0; element_index < n; ++element_index) {
            if (beforeItems.at(element_index).size() == 0) {
                continue;
            }
            
            for (int before_index : beforeItems.at(element_index)) {
                if (group.at(element_index) == group.at(before_index)) {
                    group_element_graphs.at(group.at(element_index)).addEdge(before_index, element_index);
                } else {
                    group_graph.addEdge(group.at(before_index), group.at(element_index));
                }
            }
        }
        
        // sort out based on different group dependency.
        vector<int> group_depend_result = group_graph.sort();
        vector<int> res;
        if (group_depend_result.size() < group_and_elements.size()) {
            // impossible to achieve.
            return res;
        }
        
        for (int group_index : group_depend_result) {
            vector<int> element_in_group_dependency_res = group_element_graphs.at(group_index).sort();
            if (element_in_group_dependency_res.size() != group_and_elements.at(group_index).size()) {
                res.clear();
                return res;
            }
            for (int element : element_in_group_dependency_res) {
                res.push_back(element);
            }
        }
        
        return res;
    }    
};

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值