你这个学期必须选修 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 <= 105
0 <= prerequisites.length <= 5000
prerequisites[i].length == 2
0 <= ai, bi < numCourses
prerequisites[i]
中的所有课程对 互不相同
void dfsFinish(map<int, set<int>>&keySet,stack<int>&tmpStk,vector<bool> &isRepeat,bool &ret, set<int > &memo )
{
if (ret == false)
{
return;
}
if (tmpStk.empty())
{
return;
}
int top = tmpStk.top();
if (memo.count(top))
{
isRepeat[top] = false;
tmpStk.pop();
return;
}
set<int>tmpSet = keySet[top];
for (auto itt : tmpSet)
{
if (isRepeat[itt] == true)
{
ret = false;
return ;
}
isRepeat[itt] = true;
tmpStk.push(itt);
dfsFinish(keySet, tmpStk, isRepeat, ret,memo);
}
isRepeat[top] = false;
memo.insert(top);
tmpStk.pop();
}
//0706 深度遍历 是否重复访问
bool canFinish(int numCourses, vector<vector<int>>& prerequisites)
{
if (0 == prerequisites.size())
{
return true;
}
set<int>headSet;
map<int, set<int>>keySet;
for (int i = 0; i < prerequisites.size(); i++)
{
vector<int>tmp = prerequisites[i];
if (tmp[0] == tmp[1]) //自我依赖
{
return false;
}
if (headSet.count(tmp[0]) == 0) //add head
{
headSet.insert(tmp[0]);
}
if (headSet.count(tmp[1]) == 1) //delete tail
{
headSet.erase(tmp[1]);
}
keySet[tmp[0]].insert(tmp[1]);
}
if (headSet.empty())
{
return false;
}
vector<bool> isRepeat(numCourses + 1, false);
set<int>memo;
for (auto it : headSet)
{
set<int>tmpSet = keySet[it];
stack<int>tmpStk;
tmpStk.push(it);
isRepeat[it] = true;
bool ret = true;
dfsFinish(keySet, tmpStk, isRepeat, ret,memo);
if (ret == false)
{
return false;
}
}
return true;
}