【vivo2021届秋季校招】1. 编译依赖问题
一个完整的软件项目往往会包含很多由代码和文档组成的源文件。编译器在编译整个项目的时候,可能需要按照依赖关系来依次编译每个源文件。
比如,A.cpp 依赖 B.cpp,那么在编译的时候,编译器需要先编译 B.cpp,才能再编译 A.cpp。
假设现有 0,1,2,3 四个文件,0号文件依赖1号文件,1号文件依赖2号文件,3号文件依赖1号文件,则源文件的编译顺序为 2,1,0,3 或 2,1,3,0。
现给出文件依赖关系,如 1,2,-1,1,表示0号文件依赖1号文件,1号文件依赖2号文件,2号文件没有依赖,3号文件依赖1号文件。请补充完整程序,返回正确的编译顺序。注意如有同时可以编译多个文件的情况,按数字升序返回一种情况即可,比如前述案例输出为:2,1,0,3
示例输入:
"1,2,-1,1"
输出例子:
"2,1,0,3"
题解
拓扑排序,使用优先队列(小根堆)处理:同时可以编译多个文件的情况,按数字升序返回。
import java.util.*;
public class Solution {
public String compileSeq(String input) {
String[] fileNum = input.split(",");
int n = fileNum.length;
int[] fileIds = new int[n];
// 小根堆 下标
PriorityQueue<Integer> pq = new PriorityQueue<>();
// 从没有依赖的文件开始,为-1说明该文件id不用前置文件,将id加入堆中
for (int i = 0; i < n; i++) {
fileIds[i] = Integer.parseInt(fileNum[i]);
if (fileIds[i] == -1) {
pq.offer(i);
}
}
//收集结果
StringBuilder sb = new StringBuilder();
// 利用小根堆实现拓扑排序
while (!pq.isEmpty()) {
// 可以先执行的前置文件
int fileId = pq.poll();
sb.append(fileId).append(",");
// 将所有依赖 fileId 的文件加入小根堆
for (int i = 0; i < n; i++) {
if (fileIds[i] == fileId) {
pq.offer(i);
}
}
}
//删除最后一个,
return sb.deleteCharAt(sb.length() - 1).toString();
}
public static void main(String[] args) {
Solution solution = new Solution();
String s = solution.compileSeq("1,2,-1,1");
System.out.println(s);
}
}