在采访中得到了这个问题。想知道是否有更好的解决方案:
鉴于N个任务及其中的依赖关系,请提供执行序列,以确保在不违反依赖关系的情况下执行作业。
示例文件:
5
1·4
3 2
4℃; 5
第一行是总任务数。 1< 4表示任务1必须在任务4之前执行。
一个可能的顺序是: 1 4 5 3 2
我的解决方案使用DAG存储所有数字,然后进行拓扑排序。是否有一种解决这个问题的不那么严厉的方式?:
DirectedAcyclicGraph<Integer, DefaultEdge> dag = new DirectedAcyclicGraph<Integer, DefaultEdge>(DefaultEdge.class);
Integer [] hm = new Integer[6];
//Add integer objects to storage array for later edge creation and add vertices to DAG
for(int x = 1; x <= numVertices; x++){
Integer newInteger = new Integer(x);
hm[x] = newInteger;
dag.addVertex(newInteger);
}
for(int x = 1; x < lines.size()-1; x++){
//Add edges between vertices
String[] parts = lines.get(x).split("<");
String firstVertex = parts[0];
String secondVertex = parts[1];
dag.addDagEdge(hm[Integer.valueOf(firstVertex)], hm[Integer.valueOf(secondVertex)]);
}
//Topological sort
Iterator<Integer> itr = dag.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
答案 0 :(得分:2)
正如一些用户(Gassa,shekhar suman,mhum和Colonel Panic)已经说过的那样,通过寻找拓扑排序来解决问题。只要dag中的迭代器按顺序返回元素就是正确的。 我不是DirectedAcyclicGraph类的来源,所以我无法帮助。否则,这个方法会像您一样进行解析并使用一个简单的算法(实际上,第一个出现在我的脑海中)
public static int[] orderTasks (String[] lines){
// parse
int numTasks = Integer.parseInt(lines[0]);
List<int[]> restrictions = new ArrayList<int[]>(lines.length-1);
for (int i = 1; i < lines.length; i++){
String[] strings = lines[i].split("<");
restrictions.add(new int[]{Integer.parseInt(strings[0]), Integer.parseInt(strings[1])});
}
// ordered
int[] tasks = new int[numTasks];
int current = 0;
Set<Integer> left = new HashSet<Integer>(numTasks);
for (int i = 1; i <= numTasks; i++){
left.add(i);
}
while (current < tasks.length){
// these numbers can't be written yet
Set<Integer> currentIteration = new HashSet<Integer>(left);
for (int[] restriction : restrictions){
// the second element has at least the first one as precondition
currentIteration.remove(restriction[1]);
}
if (currentIteration.isEmpty()){
// control for circular dependencies
throw new IllegalArgumentException("There's circular dependencies");
}
for (Integer i : currentIteration){
tasks[current++]=i;
}
// update tasks left
left.removeAll(currentIteration);
// update restrictions
Iterator<int[]> iterator = restrictions.iterator();
while (iterator.hasNext()){
if (currentIteration.contains(iterator.next()[0])){
iterator.remove();
}
}
}
return tasks;
}
BTW,在你的hm数组初始化中你定义它有6个元素。它将0位置保留为null(这不是问题,因为你还没有调用它)但是在一般情况下,任务的数量可能大于5然后你将拥有和IndexOutOfBoundsException
在添加边缘时,如果循环依赖,如果DAG引发的异常消息不够清楚,则用户可能会感到困惑。再说一次,因为我不知道那个班级来自哪里,我不知道。