done 苹果一个后端组的oa

题目:

/**
* The Problem:
*
* We have a list of tasks. Each task can depend on other tasks. 
* For example if task A depends on task B then B should run before A.
* 
* Implement the "getTaskWithDependencies" method such that it returns a list of task names in the correct order.
* 
* For example if I want to execute task "application A", the method should return a list with "storage,mongo,application A".
*
* List of Tasks:
*
*   - name: application A
*     dependsOn:
*       - mongo
*
*   - name: storage
*
*   - name: mongo
*     dependsOn:
*       - storage
*
*   - name: memcache
*
*   - name: application B
*     dependsOn:
*       - memcache
*
* The Java program is expected to be executed succesfully.
*/

一开始的做法:

import java.io.*;
import java.util.*;
import org.junit.*;
import org.junit.runner.*;

public class Solution { 
 private static List<String> getTaskWithDependencies(List<Task> tasks, String dependsOn) {
   // TODO: please implement logic here
   //定义 
        int numCourses = tasks.size();
        boolean[] visited = new boolean[numCourses];
        Stack<String> stack = new Stack<>();
        //判断
        //v是课程的数量 0-4
        for (int i = 0; i < numCourses; i++) {
            //有环就是空
            if (!topologicalSort(tasks, i, tasks.get(i).getName(),
                stack, visited, new boolean[numCourses])) return new ArrayList<>();
        }
        
        //定义结果
        //int[] result = new int[numCourses];
        List<String> result = new ArrayList<>();
        //往里面加
        while (!stack.isEmpty()) {
            result.add(stack.pop());
        }
        return result;
 }
  
private static boolean topologicalSort(List<Task> adj, int taskIndex, String taskName,
        Stack<String> stack, boolean[] visited, boolean[] isLoop) {
        //提前判断一下
        if (visited[taskIndex]) return true;
        if (isLoop[taskIndex]) return false;

        //设定v是有循环的,因为v是大的[],就分析这么一次。类比,task是大的,就分析一次。所以signature要改。
        isLoop[taskIndex] = true;
        //u需要具体问题具体分析。有回路就是false。类比,name需要具体问题具体分析。
        //所以怎么迁移到这道题呢?adj.get(v)是Task。那都换成Task不就行了?
        //两个不一样类型。。。注释掉会不会有影响?会,主要是中途false了就不能加了。一直是true才能加
        //别用for each循环不就行了
        if (!adj.get(taskIndex).getDependsOn().isEmpty()) {
          if (!topologicalSort(adj, taskIndex, adj.get(taskIndex).getDependsOn().toString(),
                stack, visited, isLoop)) 
        {System.out.println("false here");
                return false;}
        } else {
          if (!topologicalSort(adj, taskIndex, "",
                stack, visited, isLoop)) 
        {System.out.println("false here1");
                return false;}
        }
        //访问完v了
        visited[taskIndex] = true;

        //把课程加到stack里,后续要拿来排序。所以应该是string对吧。处理下就行了。
        System.out.println("adj.get(taskIndex).getName() = " + adj.get(taskIndex).getName());
        stack.push(adj.get(taskIndex).getName());
        return true;
    }

 public static void main(String[] args) {
   JUnitCore.main("Solution");        
 }

 @Test
 public void testGetTaskDependenciesForApplicationA() {
   Assert.assertEquals(
     Arrays.asList(
       "storage",
       "mongo",
       "application A"
     ),
     getTaskWithDependencies(TaskList.getTasks(), "application A")
   );
 }
}

/**
* Definition of a Task
*/
class Task {
 private final String name;
 private final List<String> dependsOn;

 Task(String name) {
   this(name, new ArrayList<>());
 }

 Task(String name, List<String> dependsOn) {
   this.name = name;
   this.dependsOn = dependsOn;
 }

 public String getName() { return this.name; }
 public List<String> getDependsOn() { return this.dependsOn; }
}

class TaskList {
 public static List<Task> getTasks() {
   List<Task> tasks = new ArrayList<>();

   tasks.add(new Task("application A", Arrays.asList("mongo")));
   tasks.add(new Task("storage"));
   tasks.add(new Task("mongo", Arrays.asList("storage")));
   tasks.add(new Task("memcache"));
   tasks.add(new Task("application B", Arrays.asList("memcache")));

   return tasks;
 }
}

 后来觉得不可行,把自定义的类放到递归中去,根本就无法debug。还是一开始就把自定义的类变成数字编号吧。问题是会出现两条路。

/**
* The Problem:
*
* We have a list of tasks. Each task can depend on other tasks. 
* For example if task A depends on task B then B should run before A.
* 
* Implement the "getTaskWithDependencies" method such that it returns a list of task names in the correct order.
* 
* For example if I want to execute task "application A", the method should return a list with "storage,mongo,application A".
*
* List of Tasks:
*
*   - name: application A
*     dependsOn:
*       - mongo
*
*   - name: storage
*
*   - name: mongo
*     dependsOn:
*       - storage
*
*   - name: memcache
*
*   - name: application B
*     dependsOn:
*       - memcache
*
* The Java program is expected to be executed succesfully.
*/


import java.io.*;
import java.util.*;
import org.junit.*;
import org.junit.runner.*;

public class Solution { 
 private static List<String> getTaskWithDependencies(List<Task> tasks, String dependsOn) {
   // TODO: please implement logic here
   
   //定义输入数据。
   int numTasks = 5;
   //如果需要转换,可以用hashmap对应string和编号
   int prerequisites[][]={{0,1},{1,2},{4,3}};
   
   //调用排序,获得result数组
   int[] result = findOrder(numTasks, prerequisites);
   for (int i = 0; i < result.length; i++) {
     System.out.println("result[i] = " + result[i]);
   }
   
   //如果需要转换,可以用hashmap对应string和编号
   ArrayList<String> res = new ArrayList<>();
   res.add("storage");
   res.add("mongo");
   res.add("application A");
   
   return res;
 }
  
  public static int[] findOrder(int numTasks, int[][] prerequisites) {
        List<List<Integer>> adj = new ArrayList<>(numTasks);
        for (int i = 0; i < numTasks; i++) adj.add(i, new ArrayList<>());
        for (int i = 0; i < prerequisites.length; i++) adj.get(prerequisites[i][1]).add(prerequisites[i][0]);
        boolean[] visited = new boolean[numTasks];
        Stack<Integer> stack = new Stack<>();
        for (int i = 0; i < numTasks; i++) {
            if (!topologicalSort(adj, i, stack, visited, new boolean[numTasks])) return new int[0];
        }
        int i = 0;
        int[] result = new int[numTasks];
        while (!stack.isEmpty()) {
            result[i++] = stack.pop();
        }
        return result;
    }
  
 private static boolean topologicalSort(List<List<Integer>> adj, int v, Stack<Integer> stack, boolean[] visited, boolean[] isLoop) {
        if (visited[v]) return true;
        if (isLoop[v]) return false;
        isLoop[v] = true;
        for (Integer u : adj.get(v)) {
            if (!topologicalSort(adj, u, stack, visited, isLoop)) return false;
        }
        visited[v] = true;
        stack.push(v);
        return true;
    }
  

 public static void main(String[] args) {
   JUnitCore.main("Solution");        
 }

 @Test
 public void testGetTaskDependenciesForApplicationA() {
   Assert.assertEquals(
     Arrays.asList(
       "storage",
       "mongo",
       "application A"
     ),
     getTaskWithDependencies(TaskList.getTasks(), "application A")
   );
 }
}

/**
* Definition of a Task
*/
class Task {
 private final String name;
 private final List<String> dependsOn;

 Task(String name) {
   this(name, new ArrayList<>());
 }

 Task(String name, List<String> dependsOn) {
   this.name = name;
   this.dependsOn = dependsOn;
 }

 public String getName() { return this.name; }
 public List<String> getDependsOn() { return this.dependsOn; }
}

class TaskList {
 public static List<Task> getTasks() {
   List<Task> tasks = new ArrayList<>();

   tasks.add(new Task("application A", Arrays.asList("mongo")));
   tasks.add(new Task("storage"));
   tasks.add(new Task("mongo", Arrays.asList("storage")));
   tasks.add(new Task("memcache"));
   tasks.add(new Task("application B", Arrays.asList("memcache")));

   return tasks;
 }
}

后来去stackoverflow上问了,获得这个答案(感谢德国的编辑,孟加拉国的好兄弟!世界码农一家亲!) 

其实用递归就行了,递归来来去去就是一条路,根本不会出现两条路的情况。递归学得不到位啊!

/**
* The Problem:
*
* We have a list of tasks. Each task can depend on other tasks. 
* For example if task A depends on task B then B should run before A.
* 
* Implement the "getTaskWithDependencies" method such that it returns a list of task names in the correct order.
* 
* For example if I want to execute task "application A", the method should return a list with "storage,mongo,application A".
*
* List of Tasks:
*
*   - name: application A
*     dependsOn:
*       - mongo
*
*   - name: storage
*
*   - name: mongo
*     dependsOn:
*       - storage
*
*   - name: memcache
*
*   - name: application B
*     dependsOn:
*       - memcache
*
* The Java program is expected to be executed succesfully.
*/


import java.io.*;
import java.util.*;
import org.junit.*;
import org.junit.runner.*;

public class Solution { 
private static List<String> getTaskWithDependencies(List<Task> tasks, String dependsOn) {
    //初始化一个resultString
    StringBuilder resultString = new StringBuilder();
  
    for (int i = 0; i < tasks.size(); i++) {
      System.out.println(tasks.get(i).getName());
    }
  
    //筛选出必须有name = dependsOn的每个人物自己
    Task task = tasks.stream().filter(x -> dependsOn.equalsIgnoreCase(x.getName()))
      .findAny().get();
    
    //如果非空
    if (task.getDependsOn() != null && !task.getDependsOn().isEmpty()) {
        for (String newDependsOn : task.getDependsOn()) {
            //递归一下,递归栈越深的放前面。storage先append了,然后mongo
            List<String> res = getTaskWithDependencies(tasks, newDependsOn);
            //用逗号分隔结果
            for (String ele : res) {
                resultString.append(ele).append(",");
                System.out.println("");
                System.out.println("resultString = " + resultString);
                System.out.println("");
            }
        }
    }
    //最后加上application A本身
    resultString.append(dependsOn);
    System.out.println("resultString after append = " + resultString);
    return Arrays.asList(resultString.toString().split(","));
}
  

 public static void main(String[] args) {
   JUnitCore.main("Solution");        
 }

 @Test
 public void testGetTaskDependenciesForApplicationA() {
   Assert.assertEquals(
     Arrays.asList(
       "storage",
       "mongo",
       "application A"
     ),
     getTaskWithDependencies(TaskList.getTasks(), "application A")
   );
 }
}

/**
* Definition of a Task
*/
class Task {
 private final String name;
 private final List<String> dependsOn;

 Task(String name) {
   this(name, new ArrayList<>());
 }

 Task(String name, List<String> dependsOn) {
   this.name = name;
   this.dependsOn = dependsOn;
 }

 public String getName() { return this.name; }
 public List<String> getDependsOn() { return this.dependsOn; }
}

class TaskList {
 public static List<Task> getTasks() {
   List<Task> tasks = new ArrayList<>();

   tasks.add(new Task("application A", Arrays.asList("mongo")));
   tasks.add(new Task("storage"));
   tasks.add(new Task("mongo", Arrays.asList("storage")));
   tasks.add(new Task("memcache"));
   tasks.add(new Task("application B", Arrays.asList("memcache")));

   return tasks;
 }
}

打印的log:

JUnit version 4.13.2
.application A
storage
mongo
memcache
application B
application A
storage
mongo
memcache
application B
application A
storage
mongo
memcache
application B
resultString after append = storage

resultString = storage,

resultString after append = storage,mongo

resultString = storage,


resultString = storage,mongo,

resultString after append = storage,mongo,application A

Time: 0.015

OK (1 test)

使用Stream的filter进行过滤,eg只保留男性。

Stream<Person> personStream = collection.stream().filter(
        person -> "男".equals(person.getGender())//只保留男性
);

教程:https://blog.csdn.net/qq_33829547/article/details/80279488

原文地址:https://www.cnblogs.com/immiao0319/p/15113915.html