拼多多服务端开发笔试第3题

安排任务,使其平均周转时间最小,周转时间=作业调度等待时间+作业服务时间[+作业阻塞],如果想让平均周转时间越小,那么服务时间需求越少的作业就具有更高的优先级,毕竟服务时间长的作业先完成会导致后面的所有的作业等待时间更长。

- 使用两个HashMap完成作业依赖与被依赖映射;
- 对服务时间进行排序,使用升序排序,注意排序之后需要的是排序结果的索引,即不改变数组元素;
- 从小到大依次移除没有依赖选项的任务,同时修改其他任务的依赖任务池。


import java.util.*;  public class Third { /**  5 6  1 2 1 1 1  1 2  1 3  1 4  2 5  3 5  4 5  */  /**  * 任务->被依赖任务 默认为空  */  private static Map<Integer, Set<Integer>> maps = new HashMap<>();  /**  * 任务->依赖任务  */  private static Map<Integer, Set<Integer>> tasks = new HashMap<>();  /**  * 已访问结点  */  private static Set<Integer> visited = new HashSet<>();   public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);  int n = sc.nextInt();  int m = sc.nextInt();  // 服务时间  int[] data = new int[n + 1];  data[0] = 0;   int first = 0;  // 读入数据  while (first < n) {
            data[++first] = sc.nextInt();  Set<Integer> set = new HashSet<>();  maps.put(first, set);  } // 任务依赖信息  int second = 0;  while (second < m) { int a = sc.nextInt();  int b = sc.nextInt();  // 被依赖映射  Set<Integer> set = maps.get(a);  set.add(b);  // 依赖映射  if (tasks.containsKey(b)) {
                Set<Integer> others = tasks.get(b);  others.add(a);  } else {
                Set<Integer> others = new HashSet<>();  others.add(a);  tasks.put(b, others);  }
            second++;  }
        System.out.println(maps);  System.out.println(tasks);  // 按服务时间大小排序  int[] indexes = mergeSortToIndicesASC(data);  System.out.println(Arrays.toString(indexes));  // 已处理结点数  int count = 1;  int countSum = 0;  // 处理到结点i总的等待时间  int[] wait = new int[n + 1];  wait[0] = 0;  // 任务安排  int[] res = new int[n + 1];  res[0] = 0;  // 处理任务  while (count <= n) { for (int i = 1; i <= n; i++) { if (!visited.contains(indexes[i])) {
                    Set<Integer> numberTask = tasks.get(indexes[i]);  if (numberTask == null || numberTask.isEmpty()) {
                        res[count] = indexes[i];  // 依赖项发生改变  remove(maps, tasks, indexes[i]);  visited.add(indexes[i]);  countSum = countSum + wait[count - 1] + data[indexes[i]];  wait[count] = wait[count - 1] + data[indexes[i]];  count++;  break;  }
                }
            }
        } for (int i = 1; i < res.length; i++) { if (i > 1) {
                System.out.print(" ");  }
            System.out.print(res[i]);  }
        System.out.println();  System.out.println(Arrays.toString(wait));  System.out.println(countSum * 1.0 / n);  } public static void remove(Map<Integer, Set<Integer>> maps, Map<Integer, Set<Integer>> tasks, int task) {
        Set<Integer> others = maps.get(task);  Iterator<Integer> iterator = others.iterator();  while (iterator.hasNext()) { int other = iterator.next();  tasks.get(other).remove(task);  }
    } public static int[] mergeSortToIndicesASC(int[] paraArray) { int tempLength = paraArray.length;  int[][] resultMatrix = new int[2][tempLength];   // Initialize  int tempIndex = 0;  for (int i = 0; i < tempLength; i++) {
            resultMatrix[tempIndex][i] = i;  }// Of for i  // Merge  int tempCurrentLength = 1;  // The indices for current merged groups.  int tempFirstStart, tempSecondStart, tempSecondEnd;  while (tempCurrentLength < tempLength) { // Divide into a number of groups  // Here the boundary is adaptive to array length not equal to 2^k.  for (int i = 0; i < Math.ceil(tempLength + 0.0 / tempCurrentLength) / 2; i++) { // Boundaries of the group  tempFirstStart = i * tempCurrentLength * 2;  tempSecondStart = tempFirstStart + tempCurrentLength - 1;  if (tempSecondStart >= tempLength) { break;  }// Of if  tempSecondEnd = tempFirstStart + tempCurrentLength * 2 - 1;  if (tempSecondEnd >= tempLength) {
                    tempSecondEnd = tempLength - 1;  }// Of if   // Merge this group  int tempFirstIndex = tempFirstStart;  int tempSecondIndex = tempSecondStart + 1;  int tempCurrentIndex = tempFirstStart;  while ((tempFirstIndex <= tempSecondStart)
                        && (tempSecondIndex <= tempSecondEnd)) { if (paraArray[resultMatrix[tempIndex % 2][tempFirstIndex]] <= paraArray[resultMatrix[tempIndex % 2][tempSecondIndex]]) {
                        resultMatrix[(tempIndex + 1) % 2][tempCurrentIndex] = resultMatrix[tempIndex % 2][tempFirstIndex];  tempFirstIndex++;  } else {
                        resultMatrix[(tempIndex + 1) % 2][tempCurrentIndex] = resultMatrix[tempIndex % 2][tempSecondIndex];  tempSecondIndex++;  }// Of if  tempCurrentIndex++;  }// Of while   // Remaining part  for (int j = tempFirstIndex; j <= tempSecondStart; j++) {
                    resultMatrix[(tempIndex + 1) % 2][tempCurrentIndex] = resultMatrix[tempIndex % 2][j];  tempCurrentIndex++;  }// Of for j  for (int j = tempSecondIndex; j <= tempSecondEnd; j++) {
                    resultMatrix[(tempIndex + 1) % 2][tempCurrentIndex] = resultMatrix[tempIndex % 2][j];  tempCurrentIndex++;  }// Of for j  }// Of for i  tempCurrentLength *= 2;  tempIndex++;  }// Of while  return resultMatrix[tempIndex % 2];  }// Of mergeSortToIndices
#拼多多##笔试题目#
全部评论
贪婪选择+拓扑排序,拓扑后选择目前没有依赖的顶点(如果有多个选择一个执行花销最小的一个任务,可以采用优先队列)
点赞 回复 分享
发布于 2019-07-29 00:25
可以把代码格式化一下吗。。。。。
点赞 回复 分享
发布于 2019-07-29 00:27
怎么没人讨论第四题
点赞 回复 分享
发布于 2019-07-29 07:48
我新建了一个类……然后感觉就是dijkstra算法……
点赞 回复 分享
发布于 2019-07-29 09:00
这中做法有问题吧,要求是得到平均等待时间最小,每次取能够执行的最短时间任务并不能保证,没有考虑到后面执行的任务
点赞 回复 分享
发布于 2019-07-29 10:00
1、直接用个vector数组存一下依赖关系,同时用一个数组记录每个任务在图中的入度。 2、n次遍历,每次从所有的任务中找到入度为0的任务,当有多个,优先选时间相同,时间相同优先选编号小的(字典序),这个可以通过每次从1开始遍历来实现,这样的时间复杂度是平方,但是任务数量不多可以AC,如果任务很多可以用优先队列优化为nlogn。 3、当选出上述的一个任务之后,根据图来确定哪些任务能成为新的入度为0的任务(拓扑排序)。 为了避免重复,需要一个额外的flag数组来表示哪些任务已经执行了。 这是我AC的思路,大致是这样...
点赞 回复 分享
发布于 2019-07-29 10:05

相关推荐

10-24 13:36
门头沟学院 Java
Zzzzoooo:更新:今天下午有hr联系我去不去客户端,拒了
点赞 评论 收藏
分享
冲芭芭拉鸭:你这图还挺新,偷了。
投递美团等公司10个岗位
点赞 评论 收藏
分享
评论
点赞
14
分享
牛客网
牛客企业服务