力扣--课程表--bfs+dfs

2024-03-13 12:52
文章标签 力扣 bfs dfs 课程表

本文主要是介绍力扣--课程表--bfs+dfs,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

整体思路:

 这是一道拓扑序列的题目,我们将边的方向定义成从先修课指向后修课的方向,借一下官方的题解图片,我们需要判断的是形成的这个图结构是否存在环,如果存在环,那么代表不能完成所有课程的学习。

bfs思路:

首先将每个点的入度数记录到hmap中,将每个点的后续节点记录到record中(record是一个unordered_map<int,vector<int>>结构,指的是某个节点指向的后续节点),首先遍历hmap中所有入度为0的节点,说明这些课程不需要先修课,他们可以直接被修完。将这些节点去掉,并且将该节点的后续节点的hmap值-1。再次遍历hmap,去掉入度数为0的节点....用什么结构来实现这个过程呢?队列~

代码:

C++:
class Solution {
public:bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {//广度优先搜索---记录入度unordered_map<int,int> hmap;unordered_map<int,vector<int>> record; //记录该门课程的后续课程int cnt=0;//初始化hmap,recordfor(int i=0;i<numCourses;i++){hmap[i]=0;}int len=prerequisites.size();for(int i=0;i<len;i++){int a=prerequisites[i][0];int b=prerequisites[i][1];hmap[a]+=1;record[b].push_back(a);}//将deque<int> q;//初始化qunordered_map<int,int>::iterator iter=hmap.begin();for(auto iter:hmap){if(iter.second==0){q.push_back(iter.first);hmap[iter.first]=-1;}}//while(!q.empty()){int p=q.front();  //该点入度为0,可删除q.pop_front();cnt++;int len=record[p].size();for(int i=0;i<len;i++){hmap[record[p][i]]--;}for(auto iter:hmap){if(iter.second==0){q.push_back(iter.first);hmap[iter.first]=-1;}}}if(cnt==numCourses){return true;}else{return false;}}
};

注意这句代码:

unordered_map<int,int>::iterator iter=hmap.begin();
Python:
class Solution:def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:hmap=[0]*numCourseslen_pre=len(prerequisites)record=[[] for i in range(numCourses)]cnt=0for i in range(len_pre):a=prerequisites[i][0]b=prerequisites[i][1]hmap[a]+=1record[b].append(a)q=deque()for index,value in enumerate(hmap):if value==0:q.append(index)hmap[index]=-1while q:p=q[0]q.popleft()cnt+=1len_=len(record[p])for i in range(len_):hmap[record[p][i]]-=1for index,value in enumerate(hmap):if value==0:q.append(index)hmap[index]=-1if cnt==numCourses:return Trueelse:return False

Python中的deque需要 from collections import deque

注意这句代码:(替代vector<vector<int>>)

record=[[] for i in range(numCourses)] #正确
record=[[]]* numCourses  #错误

注意这句代码:(替代key为索引的字典/替代需要查找索引的list)

for index,value in enumerate(hmap):

dfs思路:

我们利用hmap来记录节点 i 的邻接节点,利用flag来记录节点的状态(flag=0代表该点未被dfs,flag=1代表该点正在被路上的节点dfs,flag=-1代表该点已被其他节点dfs)。

大致dfs的思路是这样的(以节点 i 开始),首先判断节点 i 是否被其他节点 dfs(即flag=1),如果成立,则说明暂时无环,返回false。其次判断节点 i 是否属于正在被路上节点dfs,如果成立,则代表有环,返回true。如果该点未被访问,将该点的邻接节点依次遍历,遍历中如果有环,返回true,如果无环,将 i 节点的flag值记为-1。

代码:

C++:
class Solution {
public:bool dfs(int i,unordered_map<int,vector<int>>& hmap,vector<int>& flag){//以第i个点为起点//有环返回true,无环返回falseif(flag[i]==1){return true;}if(flag[i]==-1){return false;}flag[i]=1;int len=hmap[i].size();for(int j=0;j<len;j++){if(dfs(hmap[i][j],hmap,flag)){return true;}}flag[i]=-1;return false;}bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {int len=prerequisites.size();unordered_map<int,vector<int>> hmap;for(int i=0;i<len;i++){hmap[prerequisites[i][1]].push_back(prerequisites[i][0]);}vector<int> flag(numCourses,0);for(int i=0;i<numCourses;i++){if(dfs(i,hmap,flag)){return false;}}return true;}
};

Python:

class Solution:def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:def dfs(i,hmap:List[List[int]],flag:List[int]) -> bool:if flag[i]==1:return Trueif flag[i]==-1:return Falseflag[i]=1len_hmap=len(hmap[i])for j in range(len_hmap):if dfs(hmap[i][j],hmap,flag):return Trueflag[i]=-1return Falselen_pre=len(prerequisites)hmap=[[]for _ in range(numCourses)]for j in range(len_pre):hmap[prerequisites[j][1]].append(prerequisites[j][0])flag=[0]*numCoursesfor j in range(numCourses):if(dfs(j,hmap,flag)):return Falsereturn True

这篇关于力扣--课程表--bfs+dfs的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/804943

相关文章

hdu1254(嵌套bfs,两次bfs)

/*第一次做这种题感觉很有压力,思路还是有点混乱,总是wa,改了好多次才ac的思路:把箱子的移动当做第一层bfs,队列节点要用到当前箱子坐标(x,y),走的次数step,当前人的weizhi(man_x,man_y),要判断人能否将箱子推到某点时要嵌套第二层bfs(人的移动);代码如下:

hdu 2489 (dfs枚举 + prim)

题意: 对于一棵顶点和边都有权值的树,使用下面的等式来计算Ratio 给定一个n 个顶点的完全图及它所有顶点和边的权值,找到一个该图含有m 个顶点的子图,并且让这个子图的Ratio 值在所有m 个顶点的树中最小。 解析: 因为数据量不大,先用dfs枚举搭配出m个子节点,算出点和,然后套个prim算出边和,每次比较大小即可。 dfs没有写好,A的老泪纵横。 错在把index在d

poj 3050 dfs + set的妙用

题意: 给一个5x5的矩阵,求由多少个由连续6个元素组成的不一样的字符的个数。 解析: dfs + set去重搞定。 代码: #include <iostream>#include <cstdio>#include <set>#include <cstdlib>#include <algorithm>#include <cstring>#include <cm

poj 2195 bfs+有流量限制的最小费用流

题意: 给一张n * m(100 * 100)的图,图中” . " 代表空地, “ M ” 代表人, “ H ” 代表家。 现在,要你安排每个人从他所在的地方移动到家里,每移动一格的消耗是1,求最小的消耗。 人可以移动到家的那一格但是不进去。 解析: 先用bfs搞出每个M与每个H的距离。 然后就是网络流的建图过程了,先抽象出源点s和汇点t。 令源点与每个人相连,容量为1,费用为

POJ 3057 最大二分匹配+bfs + 二分

SampleInput35 5XXDXXX...XD...XX...DXXXXX5 12XXXXXXXXXXXXX..........DX.XXXXXXXXXXX..........XXXXXXXXXXXXX5 5XDXXXX.X.DXX.XXD.X.XXXXDXSampleOutput321impossible

ural 1149. Sinus Dances dfs

1149. Sinus Dances Time limit: 1.0 second Memory limit: 64 MB Let  An = sin(1–sin(2+sin(3–sin(4+…sin( n))…) Let  Sn = (…( A 1+ n) A 2+ n–1) A 3+…+2) An+1 For given  N print  SN Input One

hdu 6198 dfs枚举找规律+矩阵乘法

number number number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description We define a sequence  F : ⋅   F0=0,F1=1 ; ⋅   Fn=Fn

深度优先(DFS)和广度优先(BFS)——算法

深度优先 深度优先搜索算法(英语:Depth-First-Search,DFS)是一种用于遍历或搜索树或图的算法。 沿着树的深度遍历树的节点,尽可能深的搜索树的分支,当节点v的所在边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访

两数之和--力扣1

两数之和 题目思路C++代码 题目 思路 根据题目要求,元素不能重复且不需要排序,我们这里使用哈希表unordered_map。注意题目说了只对应一种答案。 所以我们在循环中,使用目标值减去当前循环的nums[i],得到差值,如果我们在map中能够找到这个差值,就说明存在两个整数的和为目标值。 如果没有找到,就将当前循环的nums[i]以及下标i放入map中,以便后续查

力扣第347题 前K个高频元素

前言 记录一下刷题历程 力扣第347题 前K个高频元素 前K个高频元素 原题目: 分析 我们首先使用哈希表来统计数字出现的频率,然后我们使用一个桶排序。我们首先定义一个长度为n+1的数组,对于下图这个示例就是长度为7的数组。为什么需要一个长度为n+1的数组呢?假如说总共有三个数字都为1,那么我们需要把这个1放在数组下标为3的位置,假如说数组长度为n,对于这个例子就是长度为3,那么它的