【每日Leetcode】拓扑排序系列

文摘   职场   2024-07-09 13:57   上海  
【210. 课程表 II】

现在你总共有 numCourses 门课需要选,记为 0 到 numCourses - 1。给你一个数组 prerequisites ,其中 prerequisites[i] = [ai, bi] ,表示在选修课程 ai 前 必须 先选修 bi 。

  • 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示:[0,1] 。

返回你为了学完所有课程所安排的学习顺序。可能会有多个正确的顺序,你只要返回 任意一种 就可以了。如果不可能完成所有课程,返回 一个空数组 。

来源:力扣(LeetCode)

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

class Solution {public:    vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {        vector<int> res;        queue<int> q;        vector<multiset<int>> edges(numCourses);        map<int, int> rec;        for (auto& it: prerequisites) {            edges[it[1]].insert(it[0]);            rec[it[0]]++;        }        for (int i = 0; i < numCourses; ++i) {            if (rec.find(i) == rec.end()) {                q.push(i);            }        }        while (!q.empty()) {            int tmp = q.front();            q.pop();            res.push_back(tmp);            for (auto& n: edges[tmp]) {                rec[n]--;                if (rec[n] == 0) {                    q.push(n);                }            }        }        if (res.size() == numCourses)            return res;        else return vector<int>();    }};

【310. 最小高度树】
树是一个无向图,其中任何两个顶点只通过一条路径连接。换句话说,任何一个没有简单环路的连通图都是一棵树。

给你一棵包含 n 个节点的树,标记为 0 到 n - 1 。给定数字 n 和一个有 n - 1 条无向边的 edges 列表(每一个边都是一对标签),其中 edges[i] = [ai, bi] 表示树中节点 ai 和 bi 之间存在一条无向边。

可选择树中任何一个节点作为根。当选择节点 x 作为根节点时,设结果树的高度为 h 。在所有可能的树中,具有最小高度的树(即,min(h))被称为 最小高度树 。

请你找到所有的 最小高度树 并按 任意顺序 返回它们的根节点标签列表。

树的 高度 是指根节点和叶子节点之间最长向下路径上边的数量。

来源:力扣(LeetCode)

链接:https://leetcode.cn/problems/minimum-height-trees/description/

越靠近里面的节点越有可能是最小高度树的顶点。因此,不断把原来的图给剪掉一圈叶子节点,形成一个缩小的新的图。最后找到的就是两边同时向中间靠近的节点,那么这个中间节点就相当于把整个距离二分了,就是到两边距离最小的点。

class Solution {public:    vector<int> findMinHeightTrees(int n, vector<vector<int>>& edges) {        vector<int> res;        if (n == 1) {            return {0};        }        vector<int> degree(n);        vector<vector<int>> graph(n, vector<int>());        for (auto& e: edges) {            degree[e[0]]++;            degree[e[1]]++;            graph[e[0]].push_back(e[1]);            graph[e[1]].push_back(e[0]);        }        queue<int> q;        for (int i = 0; i < n; ++i) {            if (degree[i] == 1) q.push(i);        }        while (!q.empty()) {            res.clear();            int len = q.size();            for (int i = 0; i < len; ++i) {                int tmp = q.front();                q.pop();                res.push_back(tmp);                vector<int> neighbours = graph[tmp];                for (auto& neighbour: neighbours) {                    degree[neighbour]--;                    if (degree[neighbour] == 1) {                        q.push(neighbour);                    }                }            }        }        return res;    }};



【329. 矩阵中的最长递增路径

给定一个 m x n 整数矩阵 matrix ,找出其中 最长递增路径 的长度。

对于每个单元格,你可以往上,下,左,右四个方向移动。你 不能 在 对角线 方向上移动或移动到 边界外(即不允许环绕)。

来源:力扣(LeetCode)

链接:https://leetcode.cn/problems/longest-increasing-path-in-a-matrix/description/

将矩阵看成一个有向图,计算每个单元格对应的出度,即有多少条边从该单元格出发。从所有出度为 0 的单元格开始搜索。

class Solution {public:    vector<vector<int>> dir = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}};    int longestIncreasingPath(vector<vector<int>>& matrix) {        if (matrix.size() == 0 || matrix[0].size() == 0) {            return 0;        }        int m = matrix.size();        int n = matrix[0].size();        vector<vector<int>> outdegrees(m, vector<int>(n));        for (int i = 0; i < m; ++i) {            for (int j = 0; j < n; ++j) {                for (int k = 0; k < 4; ++k) {                    int newX = i + dir[k][0];                    int newY = j + dir[k][1];                    if (newX >= 0 && newX < m && newY >= 0 && newY < n && matrix[newX][newY] > matrix[i][j]) {                        outdegrees[i][j]++;                    }                }            }        }        queue<pair<int, int>> q;        for (int i = 0; i < m; ++i) {            for (int j = 0; j < n; ++j) {                if (outdegrees[i][j] == 0) {                    q.emplace(i, j);                }            }        }        int ans = 0;        while (!q.empty()) {            ++ans;            int len = q.size();            for (int i = 0; i < len; ++i) {                int x, y;                tie(x, y) = q.front();                q.pop();                for (int k = 0; k < 4; ++k) {                    int newX = x + dir[k][0];                    int newY = y + dir[k][1];                    if (newX >= 0 && newX < m && newY >= 0 && newY < n && matrix[newX][newY] < matrix[x][y]) {                        outdegrees[newX][newY]--;                        if (outdegrees[newX][newY] == 0) {                            q.emplace(newX, newY);                        }                    }                }            }        }        return ans;    }};

Arrietty刷题日记
清华计算机系学霸带你刷Leetcode(求职面试/保研考研/转计算机行业...)