Leetcode 207 课程表系列 拓扑排序 PHP

285 阅读1分钟

207 课程表
你这个学期必须选修 numCourse 门课程,记为 0 到 numCourse-1 。

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

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

 

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/co… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

第一次做图的拓扑排序相关。 顺便记录一下拓扑排序。

function canFinish($numCourses, $prerequisites) {
        $edges = array_fill(0, $numCourses, []);
        $indegree = [];
        //统计出各个节点的邻接点放到edgs,相关节点的入度情况。
        //选好前导节点和当前节点
        foreach ($prerequisites as $prerequisite) {
            $cur = $prerequisite[0];
            $pre = $prerequisite[1];
            $edges[$pre][] = $cur;
            $indegree[$cur]++;
        }

		//找到所有入度为0的节点,准备模拟去边操作
        $queue = new SplQueue();
        for ($i = 0; $i < $numCourses; $i++) {
            if ($indegree[$i] == 0) {
                $queue->enqueue($i);
            }
        }

        $res = 0;
        while (!$queue->isEmpty()) {
            $res++;
            //开始模拟去边操作。去掉当前节点
            $u = $queue->dequeue();
            foreach ($edges[$u] as $v) {
            	//当前节点的入度减一,
                $indegree[$v]--;
                //减到0就可以入队,之后就可以从该节点继续去边了。
                if ($indegree[$v] == 0) {
                    $queue->enqueue($v);
                }
            }
        }
        //这道题判断的是是否能够学完所有课程,也就是能不能正好把所有的点都遍历到。
        return $res == $numCourses;
    }

课程表2

这个是给出一个可以学完所有课程的顺序。

function findOrder($numCourses, $prerequisites) {
        //边
        $edge = array_fill(0, $numCourses, []);
        //入度
        $in_degree = array_fill(0, $numCourses, 0);
        //同样还是先搞出所有边,节点的入度情况。
        foreach ($prerequisites as $prerequisite) {
            //先导课程
            $pre = $prerequisite[1];
            $cur = $prerequisite[0];
            $edge[$pre][] = $cur;//[2,1],1-->2
            $in_degree[$cur]++;
        }
        $queue = new SplQueue();
        //从一个入度为0的节点开始学习
        for ($i = 0; $i < $numCourses; $i++) {
            //找到所有度为0的
            if ($in_degree[$i] == 0) {
                $queue->enqueue($i);
            }
        }

        $res = [];
        while (!$queue->isEmpty()) {
            $top = $queue->dequeue();
            $res[] = $top;
            $edges = $edge[$top];
            foreach ($edges as $e) {
                $in_degree[$e]--;
                if ($in_degree[$e] == 0) {
                    $queue->enqueue($e);
                }
            }
        }

        return count($res) == $numCourses ? $res : [];
    }