【算法】【线性表】【数组】课程表
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 <= 2000
0 <= prerequisites.length <= 5000
prerequisites[i].length == 2
0 <= ai, bi < numCourses
prerequisites[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; } }
哈哈哈,虽然过了,但是打败的人是不是太少了。。。。我空了得再寻思寻思。
加油。
分类:
算法 / 数组
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2023-03-18 【InheritableThreadLocal】InheritableThreadLocal的实现机制和原理