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 thei
-th item in the sorted array (to the left of thei
-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;
}
};