1. 题目
参考链接: 检测循环依赖
现有n个编译项,编号为0 ~ n-1。给定一个二维数组,表示编译项之间有依赖关系。如[0, 1]表示1依赖于0。
若存在循环依赖则返回空;不存在依赖则返回可行的编译顺序。
2. 题解
若给定一个依赖关系是[[0,2],[1,2],[2,3],[2,4]],如图所示
可以看出,它们之间不存在循环依赖。
可行的编译序列是[0,1,2,3,4],也可以是[1,0,2,4,3]等。
拓扑排序可以求这样的一个序列。可以看出,这个序列结果可能不唯一。
拓扑排序算法过程:
- 选择图中一个入度为0的点,记录下来
- 在图中删除该点和所有以它为起点的边
- 重复1和2,直到图为空或没有入度为0的点。
代码实现应该就很好理解了~我们借助BFS来实现拓扑排序,队列中存储入度为0的点。
下面提供 Java 的代码。推荐记住背下来,
类似的拓扑排序题目: 算法—LeetCode 207. 课程表
public class HaveCircularDependency {
class Solution {
public List<Integer> haveCircularDependency(int n, int[][] prerequisites) {
int[] inDegrees = new int[n];
List<List<Integer>> adjLists = new ArrayList<>();
Queue<Integer> queue = new LinkedList<>();
List<Integer> ans = new ArrayList<>();
for (int i = 0; i < n; i++) {
adjLists.add(new ArrayList<>());
}
for (int i = 0; i < prerequisites.length; i++) {
int cur = prerequisites[i][0];
int next = prerequisites[i][1];
inDegrees[next]++;
adjLists.get(cur).add(next);
}
for (int i = 0; i < inDegrees.length; i++) {
if (inDegrees[i] == 0) {
queue.offer(i);
}
}
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
int cur = queue.poll();
ans.add(cur);
List<Integer> adjList = adjLists.get(cur);
for (int adj : adjList) {
inDegrees[adj]--;
if (inDegrees[adj] == 0) {
queue.offer(adj);
}
}
}
}
if (ans.size() == n) {
return ans;
} else {
return null;
}
}
}
public static void main(String[] args) {
Solution solution = new HaveCircularDependency().new Solution();
int[][] p = {{0, 2}, {1, 2}, {2, 3}, {2, 4}};
List<Integer> ans = solution.haveCircularDependency(5, p);
for (Integer an : ans) {
System.out.println(an);
}
}
}