【算法】【线性表】【数组】课程表
1 题目
你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 1 。
在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出,其中 prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai 则 必须 先学习课程 bi 。
- 例如,先修课程对
[0, 1]表示:想要学习课程0,你需要先完成课程1。
请你判断是否可能完成所有课程的学习?如果可以,返回 true ;否则,返回 false 。
示例 1:
输入:numCourses = 2, prerequisites = [[1,0]] 输出:true 解释:总共有 2 门课程。学习课程 1 之前,你需要完成课程 0 。这是可能的。
示例 2:
输入:numCourses = 2, prerequisites = [[1,0],[0,1]] 输出:false 解释:总共有 2 门课程。学习课程 1 之前,你需要先完成课程 0 ;并且学习课程 0 之前,你还应先完成课程 1 。这是不可能的。
提示:
1 <= numCourses <= 20000 <= prerequisites.length <= 5000prerequisites[i].length == 20 <= ai, bi < numCoursesprerequisites[i]中的所有课程对 互不相同
2 解答
这道题主要就是判断是否存在死循环,第一次我递归这么写的:
class Solution { public boolean canFinish(int numCourses, int[][] prerequisites) { // 为空或者就一个直接返回 if (prerequisites == null || prerequisites.length <= 1) { return true; } Map<Integer, List<Integer>> map = new HashMap<>(prerequisites.length); for (int[] prerequisite : prerequisites) { List<Integer> list = map.computeIfAbsent(prerequisite[0], (a) -> new ArrayList<>()); list.add(prerequisite[1]); } for (int[] prerequisite : prerequisites) { Set<Integer> sets = new HashSet<>(); sets.add(prerequisite[0]); boolean res = chargeRecursion(sets, map, prerequisite[1]); if (res) { return false; } } return true; } private static boolean chargeRecursion(Set<Integer> way, Map<Integer, List<Integer>> map, Integer current) { if (Objects.isNull(current)) { return false; } if (way.contains(current)) { return true; } List<Integer> list = map.get(current); if (list == null || list.size() <= 0) { return false; } for (Integer item : list) { // 只要有一个循环就返回false Set<Integer> sets = new HashSet<>(way); sets.add(current); boolean itemRes = chargeRecursion(sets, map, item); if (itemRes) { return true; } } return false; } }
有个 2000 的测试用例超时了,然后我加了一个 Set 如果这个课程判断过了,就不需要再递归了,我修改完的如下:
class Solution { public boolean canFinish(int numCourses, int[][] prerequisites) { // 为空或者就一个直接返回 if (prerequisites == null || prerequisites.length <= 1) { return true; } Set<Integer> alreadyGet = new HashSet<>(); // 表示该课程的前课程 Map<Integer, List<int[]>> inMap = Arrays.stream(prerequisites).collect(Collectors.groupingBy(i -> i[0])); for (int i = 1; i <= numCourses; i++) { List<int[]> list = inMap.get(i); // 表示该课程没要前置的课程,略过 if (Objects.isNull(list)) { continue; } // 如果已经可以得到该课程了 直接略过 if (alreadyGet.contains(i)) { continue; } // 有前置的看每个课程都能学到么 for (int[] cur : list) { Set<Integer> sets = new HashSet<>(); sets.add(cur[0]); boolean chargeGet = chargeGet(inMap, alreadyGet, sets, cur[1]); if (!chargeGet) { return false; } } alreadyGet.add(i); } return true; } private static boolean chargeGet(Map<Integer, List<int[]>> inMap, Set<Integer> alreadyGet, Set<Integer> way, int current) { List<int[]> list = inMap.get(current); if (list == null || list.size() <= 0) { return true; } if (alreadyGet.contains(current)) { return true; } for (int[] item : list) { if (way.contains(item[1])) { return false; } Set<Integer> sets = new HashSet<>(way); sets.add(item[0]); boolean itemRes = chargeGet(inMap, alreadyGet, sets, item[1]); if (!itemRes) { return false; } } alreadyGet.add(current); return true; } }
哈哈哈,虽然过了,但是打败的人是不是太少了。。。。我空了得再寻思寻思。

加油。

浙公网安备 33010602011771号