问题:课程表

现在你总共有 n 门课需要选,记为 0 到 n-1

在选修某些课程之前需要一些先修课程。 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们: [0,1]

给定课程总量以及它们的先决条件,判断是否可能完成所有课程的学习?

示例 1:

输入: 2, [[1,0]]
输出: true
解释: 总共有 2 门课程。学习课程 1 之前,你需要完成课程 0。所以这是可能的。

示例 2:

输入: 2, [[1,0],[0,1]]
输出: false
解释: 总共有 2 门课程。学习课程 1 之前,你需要先完成​课程 0;并且学习课程 0 之前,你还应先完成课程 1。这是不可能的。

说明:

  1. 输入的先决条件是由边缘列表表示的图形,而不是邻接矩阵。详情请参见图的表示法
  2. 你可以假定输入的先决条件中没有重复的边。

提示:

  1. 这个问题相当于查找一个循环是否存在于有向图中。如果存在循环,则不存在拓扑排序,因此不可能选取所有课程进行学习。
  2. 通过 DFS 进行拓扑排序 - 一个关于Coursera的精彩视频教程(21分钟),介绍拓扑排序的基本概念。
  3. 拓扑排序也可以通过 BFS 完成。

链接:https://leetcode-cn.com/problems/course-schedule/description/

分析:

1,一门课的先修课可能有多个,只要有一个没学就没法学

2,如果进行一轮后,没有新增学到的课,那么后续也不会再增加了

3,如果学到的课就是课程数量,则学了所有的,否则学不完。

所以可以设定如下数据结构:

class Class
{
public:
int Num=INT_MAX; //为止
int Status=; // 未学习
vector<int> dps;
};

Num是课程编号,Status是课程状态,0表示没学,1表示学了,dps表示以来课程。

可以假设所有的课程都不依赖任何课,初始化完成后,根据依赖关系更新,然后找到不依赖其他课的课程,

以没有先修课的课程为基础,持续更新, 直到不再新增学到的课程位置。

更新方式为:如果一个课程的先修课都已经学过了,这门课也可以学习。

AC Code:

class Class
{
public:
int Num=INT_MAX; //为止
int Status=; // 未学习
vector<int> dps;
};
class Solution {
public: bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
bool ret = false;
//如果能找到一个起始课程,即不依赖任何课程的,从这个开始学习所有
//如果找不到,则不能进行
vector<Class> classes;
for (int i = ; i < numCourses; i++)
{
Class tmp;
tmp.Num = i;
tmp.Status = ;
tmp.dps = vector<int>();
classes.emplace_back(tmp);
}
int n = prerequisites.size();
sort(prerequisites.begin(), prerequisites.end());
for (int i = ; i <n; i++)
{
int tmpnum = prerequisites[i].first;
int depnum = prerequisites[i].second;
for (int j = ; j < classes.size(); j++)
{
if (classes[j].Num == tmpnum)
{
classes[j].dps.emplace_back(depnum);
break;
}
}
} //找到所有的不依赖其他的课程,并且从哪些出发得打所有的不依赖的课程
int learned = ;
vector<int> learnedclass;
for (int i = ; i < classes.size(); i++)
{
if (classes[i].dps.size() == )
{
classes[i].Status = ;
learned++;
learnedclass.emplace_back(classes[i].Num);
}
}
while (true)
{
int currentlearned = learned;
for (int i = ; i < classes.size(); i++)
{
if (classes[i].Status == )
{
continue;
}
else
{
//这门课没学,看先修课有没有学
vector<int> tmpre = classes[i].dps;
int learnflag = ;
for (int j = ; j < tmpre.size(); j++)
{
if (find(learnedclass.begin(), learnedclass.end(), tmpre[j]) == learnedclass.end())
{
learnflag = ; //有先修课没学,学不了了
break;
}
}
if (learnflag == )
{
//这门课可以学
classes[i].Status = ;
learned++;
learnedclass.emplace_back(classes[i].Num);
} }
}
if (currentlearned == learned)
{
//没有增加学习的课程,可以结束了
//if(learned == )
return learned == numCourses;
}
} return ret;
}
};

其他:

1.QQ群里有人提到这个题,周赛第四题没搞懂dp状态转移方程,解决这个问题消磨时间吧。

提示中有提到图论等知识,不过也就学数据结构的时候学过这个,平时不怎么用,或者说不知道主动去用,没用图论的知识,虽然过了,效率比较低,以后有机会好好补补相关知识。

2.太冷动手,没太大兴趣看了,不过可以优化的地方有,一门课是否能学,看其先修课是否已经学过了,那么下一次更新的时候,再次查看就浪费时间,可以看缺了哪些课,这样待处理的数据会逐渐减少避免重复运算。

3.用时最短code:

 static const auto _ = []()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
return nullptr;
}(); class Solution {
vector<int> *vex; //vex[a]={b,c}:要学习a,须先学b,c
char *visit; //0:从未访问,1:正在访问,2:曾经访问
//若成环,返回false
bool DFS(int vID){
if(visit[vID]==)
return false; //成环了
if(visit[vID]==){ //0:从未访问
visit[vID]=; //1:正在访问
for(int i=;i<vex[vID].size();++i){
if(!DFS(vex[vID][i]))return false; //成环了
}
visit[vID]=; //2:曾经访问
}
return true; //访问过了
}
public:
bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
vex= new vector<int>[numCourses];
visit= new char[numCourses];
fill(visit,visit+numCourses,); //0:从未访问
for(int i=;i<prerequisites.size();++i){
auto &edge=prerequisites[i];
vex[edge.first].push_back(edge.second); //[1,0],学习课程 1 之前,你需要完成课程 0。
}
//逐个访问
for(int i=;i<numCourses;++i){
if(!DFS(i))return false;
}
return true; //没有成环即可
}
};

LeetCode207 课程表的更多相关文章

  1. [Swift]LeetCode207. 课程表 | Course Schedule

    There are a total of n courses you have to take, labeled from 0 to n-1. Some courses may have prereq ...

  2. Leetcode207. Course Schedule课程表

    现在你总共有 n 门课需要选,记为 0 到 n-1. 在选修某些课程之前需要一些先修课程. 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们: [0,1] 给定课程总量以及它 ...

  3. sql面试题(学生表_课程表_成绩表_教师表)

    原帖链接:http://bbs.csdn.net/topics/280002741 表架构 Student(S#,Sname,Sage,Ssex) 学生表 Course(C#,Cname,T#) 课程 ...

  4. 设有一数据库,包括四个表:学生表(Student)、课程表(Course)、成绩表(Score)以及教师信息表(Teacher)。

    一.            设有一数据库,包括四个表:学生表(Student).课程表(Course).成绩表(Score)以及教师信息表(Teacher).四个表的结构分别如表1-1的表(一)~表( ...

  5. [deviceone开发]-课程表的例子

    一.简介 这个例子是根据一个真实app的一个页面的需求来实现的demo,通过动态add ui的方式,动态bind数据构建一个完整的课程表示例.示例并不完善,但是可以给大家一个启发. 二.效果图 三.相 ...

  6. android课程表的实现

    //图片下方的码段主要实现了课程表所要显示的基本布局,采用ondraw的方法. //别的内容可以根据自己兴趣添加,下面是本人做的,仅供参考.                  package com. ...

  7. 爬虫再探实战(五)———爬取APP数据——超级课程表【四】——情感分析

    仔细看的话,会发现之前的词频分析并没有什么卵用...文本分析真正的大哥是NLP,不过,这个坑太大,小白不大敢跳...不过还是忍不住在坑边上往下瞅瞅2333. 言归正传,今天刚了解到boson公司有py ...

  8. SQL 存储过程(学生,课程表,选修表)

    SQL 存储过程(学生,课程表,选修表) 一.存储过程的分类 在SQL Server中存储过程分过两类: 1)系统存储过程("sp_"作为前缀) 2)用户自定义存储过程 二.创建和 ...

  9. SQL 触发器(学生,课程表,选修表)

    SQL 触发器(学生,课程表,选修表) 触发器是一种特殊类型的存储过程,它不由用户通过命令来执行,而是在用户对表执行了插入,删除或修改表中数据等操作时激活执行.可以这样形容:存储过程像一个遥控炸弹,我 ...

随机推荐

  1. c++ 面试整理

    1. 继承方式 public    父类的访问级别不变 protected    父类的public成员在派生类编程protected,其余的不变 private        父类的所有成员变成pr ...

  2. LinuxOS

    Linux 操作系统必须完成的两个主要目的 与硬件部分交互, 为包含在硬件平台上的所有底层可编程部件提供服务 为运行在计算机系统上的应用程序(即所谓的用户空间)提供执行环境 一些操作系统运行所有的用户 ...

  3. Qt 学习(4)

    Qt UI 文件机制 使用 Qt 设计界面程序时,若界面是静态的,可以借助 Qt Designer 进行所见即所得的界面设计.设计好界面后,在界面类中对 ui 对象进行操作非常方便. QtCreato ...

  4. ubuntu 更改源

    1) 备份原来的源 cp /etc/apt/source.list /etc/apt/source.list.old 2) 用下面的文件覆盖 /etc/apt/source.list # 163(非教 ...

  5. Redis-Service.Stack的初级使用

    主要解决Redis服务器带有密码的情况下初始化. 创建RedisHelper类,直接贴代码: using ServiceStack.Redis;using System;class RedisHelp ...

  6. golang精华资源

    转载自:http://blog.csdn.net/songbohr/article/details/13292261 1.Learning Go <学习Go语言> http://www.m ...

  7. c#比较两个字符串

    1. String.Compare(str1, str2) == 0  或者  str1.CompareTo(str2) == 0 2. str1.Equals(str2)  或者 String.Eq ...

  8. 存储过程 返回值 procedure return values

    存储过程有三种返回: 1. 用return返回int型数据 2. 用返回参数返回结果,可以返回各种数据类型(通过游标来循环查询结果每一行) 3. 直接在存储过程中用select返回结果集,可以是任意的 ...

  9. 应该知道的一些Markdown语法

    目录 快速输入标题 斜体和粗体,删除线 分隔线 外链接 无序列表 有序列表 定义型列表 插入图片 文字引用 标签分类 表格 行内代码块 代码段 注脚 待办事宜 Todo 列表 显示当前文章的目录 快速 ...

  10. Linux 作业调度器 crond

    linux缺省会启动crond进程,crond进程不需要用户启动.关闭.  需要启动/关闭cron /sbin/service crond start --启动服务 /sbin/service cro ...