【图】Leetcode 797,207 ,210排课表问题 ,三种方法遍历,拓扑排序,回溯解决课程表问题

此篇文章讲解了图的两种数据结构,怎样构造图,和图遍历的模板。

由此引出leetcode 797所有可能通路 ,leetcode 207 课程表 ,leetcode 210 课程表II的解答。

解决了图问题中常出现:DFS遍历图,回溯法遍历图,环检测,拓扑排序的问题。

目录

一、 图的基础

(1)图有两种数据结构构成。

(2)leetcode中图常用的构造方法 

(3)图的遍历方法

 二、leetcode 207 课程表

三、3种方法解答 Leetcode 210 课程表II

方法1)图遍历

方法2) 拓扑排序

四、图的遍历和回溯两种方法解决 leetcode 797 所有可能的路径

1)图的遍历解法

2)回溯算法解法


一、 图的基础

(1)图有两种数据结构构成。

1)邻接矩阵 :即用V-V矩阵来代表每个顶点和边,V代表顶点。如果是无加权图则用简单的二维布尔数组表示。加权图则可以用二维数组来表示边的距离。它的好处是访问很快,缺点是费空间。如果图有很多顶点但是边不多,则造成不必要的空间损失。这时候,接邻列表就很有优势了。

 

2)接邻列表:每个顶点接一个列表,代表相邻的顶点。这样空间使用就从上一个表示方法 V * V

降到了 V + E. 每次添加边,提供了固定的时间。 同时节约了空间。

(2)leetcode中图常用的构造方法 

leetcode中使用邻接表的构图比较多,以下是建立图的函数。

List<Integer>[] buildGraph(int numVertex, int[][] edges){
  List<Integer>[] graph = new LinkedList[numCourses];
  for(int[] edge : edges){
  int from = edge[0];
  int to = edge[1];
  graph[from].add(to);
}

(3)图的遍历方法

图的数据结构就是多叉树的延伸,多叉树就是二叉树的延伸,二叉树就是链表的延伸。我们二叉树的数据结构中也有两种:一是用数组表示的堆,二是更加常见的用列表表示的树。因为leetcode中更加常出现的结构是邻接列表,也就是底层数据结构是列表。所以与二叉树的遍历存在着非常高的相似性。我们一起来看一下。

二叉树的遍历:

class TreeNode{
int val;
TreeNode leftchild;
TreeNode rightchild;
}

traverse(TreeNode root){
   if(root == null) return;
   //前序遍历
   traverse(root.leftchild);
   //中序遍历
   traverse(root.rightchild);
   //后序遍历
}

与多叉树的遍历十分的类似。多叉树的遍历框架:

class TreeNode{
int val;
TreeNode[] children;
}

traverse(TreeNode root){
   if(root == null) return;
   for(TreeNode node : children){
   traverse(node);
   }
}

图和多叉树不同之处在于,图可能有环的。你从图的一个节点开始遍历,很可能又会到这个节点。所以我们会加入visit[] 数组来避免你走回头路:

class Vertex{
int val;
Vertex[] neighbours;}

void traverse(Graph g, Vertex s){
if(visit[s]) return
// 将当前节点 s 标记为已经遍历
visit[s] = true;
for(Vertex v : g.neighbours(s)){
   traverse(g, v)
}

}

那有些图不是所有的节点都是相连怎么办呢?加一个for循环将所有节点都作为起点都调用一下traverse()函数就可以了。如下图:

class Vertex{
int val;
Vertex[] neighbours;}

void traverseAllGraph(Graph g, int v){
    visited = new boolean[v];
    for(int i=0; i< v; i++){
       traverse(g,i);
    }
}

void traverse(Graph g, Vertex s){
if(visit[s]) return
// 将当前节点 s 标记为已经遍历
visit[s] = true;
for(Vertex v : g.neighbours(s)){
   traverse(g, v)
}

}

我想知道哪里有环怎么办呢?这就引出了判断有向图是否存在环的问题。

递归函数看成一个在递归树上游走的指针的话,traverse就是在图上游走的指针,只需要在添加一个bool

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
系统采用“并行回溯”的算法,只需设置好学校基本信息和排课的各项限制条件后,其余事情则由计算机来完成。课表完全自动化(也可手工安),完后可进行调整,采用随机安方式,具有排课速度快、准确率高、效果好,并能自动计算教师教学工作量,多种格式的班级、教师、全校课程表的输出。主要功能包括:课表管理(新建、打开、删除课表)、基本设置(年级、班级、教师、课程)、教学设置(上课时间、课时、教师任课)、排课设置(班级课表排课条件、科目优先、排课选项)、教师安、课程安(自动、手动)、课表调整(单向、双向、拖动)、课程报表(班级课表、教师课表、教师任课表等)。 排课思路 课程安: 在设置好学校基本信息、排课的各项限制条件,并好教师授课表后,可按手工或自动排课进行课程表。 课程优先级: 根据具体情况,我们所学课程有专业课和基础课之分,基础课先,而后是专业课。 手动排课: 由教师一门一门课程进行设置,由系统提示是否教师冲突或课程是否多或少。对于课程安极其复杂的学校且用自动排课无法出满意课程表的学校,可选择此种方式排课,至少教师排课时的课程数是否正确和教师是否冲突的问题。 自动排课课程表采用"并行回溯"的算法,按年级班级顺序一节一节排课,若到某位置有冲突,系统回溯上一断点位置,重新安,直到课程表全部出为止。排课时充分考虑到课程的均匀性(即课程安尽可能均匀,如语文一周10节,若一周上5天的话尽可能每天安两节课)和教师授课的均匀性(如张三教师一周5天共上15节,则尽可能安每天3节课,且3节课不连续安在如123或234接等)。课表完全自动化,并采用随机安方式,具有排课速度快、准确率高的特点。对出的课程表不满意可进行调课或直接在课程报表中进行更改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值