你这个学期必须选修 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]
中的所有课程对 互不相同
方法一:暴力求解
class Solution {
public:
//错误1:将fin!=numCourses写为fin!=0
//2:一个课程,可能有多个限制(1,0)(1,2)只用map<int,int>记录会覆盖导致错误,通过numsourses和prerequisites的长度可以分析出来
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
vector<int>learnd(numCourses,0);
int fin=0; //记录已经学完的课程数,当两轮循环剩余的课程数相同,表示不可能
unordered_map<int,vector<int>>relation ;
for(int i=0;i<prerequisites.size();i++){
relation[prerequisites[i][0]].push_back(prerequisites[i][1]);
}
while(fin!=numCourses){
int pre=fin;//记录本轮开始之前学完的课程数
for(int i=0;i<numCourses;i++){
if(learnd[i]==0){//未学习
//判断关联性课程是否已经学习
if(relation.find(i)!=relation.end()){//存在关联关系
vector<int>need=relation[i];
int flag=1;
for(int j=0;j<need.size();j++){
int cur=need[j];
if(learnd[cur]==0){//有未学习完的课程
flag=0;
}
}
if(flag==1){//相关联的课程已经学习,则当前课程也可以学习
learnd[i]=1;
fin++;
}
}
else{//无相关联关系,该课程可以直接学习
learnd[i]=1;
fin++;
}
}
}
cout<<fin;
if(pre==fin&&fin!=numCourses){//剩余课程无法学习
return false;
}
}
return fin==numCourses;
}
};
代码问题:空指针异常(即访问未初始化的指针或数组)
这里的 learnd
是一个空的 vector<int>
,但你尝试通过索引来访问和赋值它的元素。这会导致未定义行为,因为 learnd
还没有任何分配的空间,所以尝试访问 learnd[i]
会导致空指针异常。
vector<int>learnd;
for(int i=0;i<numCourses;i++){
learnd[i]=0; //暂未学习,1表示已经学习
}
解决:在使用 learnd
之前,你应该初始化它的大小
vector<int> learnd(numCourses, 0); // 初始化大小为 numCourses 的 vector,每个元素都初始化为 0