图算法-LeetCode 133、207(拓扑排序,邻接表建立)
- 2019 年 10 月 11 日
- 筆記
点击上方“算法工程师之路”,选择“星标”公众号
重磅干货,第一时间送达
作者:TeddyZhang,公众号:算法工程师之路
贪心算法问题:LeetCode #133 #207
编程题
【LeetCode #133】克隆图
给定无向连通图中一个节点的引用,返回该图的深拷贝(克隆)。图中的每个节点都包含它的值 val(Int) 和其邻居的列表(list[Node])。

解释: 节点 1 的值是 1,它有两个邻居:节点 2 和 4 。 节点 2 的值是 2,它有两个邻居:节点 1 和 3 。 节点 3 的值是 3,它有两个邻居:节点 2 和 4 。 节点 4 的值是 4,它有两个邻居:节点 1 和 3 。
提示:
- 节点数介于 1 到 100 之间。
- 无向图是一个简单图,这意味着图中没有重复的边,也没有自环。
- 由于图是无向的,如果节点 p 是节点 q 的邻居,那么节点 q 也必须是节点 p 的邻居。
- 必须将给定节点的拷贝作为对克隆图的引用返回。
解题思路:
克隆图,并且是无向连通图,因此可以使用map来保存两个节点之间的连接关系,如果在map中没有该节点tmp,则新建节点tmp_copy将该节点存入map中,然后遍历该节点的所有邻居,并递拷贝其所有邻居节点至tmp_copy的邻居数组中。
C++代码:
/* // Definition for a Node. class Node { public: int val; vector<Node*> neighbors; Node() {} Node(int _val, vector<Node*> _neighbors) { val = _val; neighbors = _neighbors; } }; */ class Solution { public: map<Node*,Node*> mp; Node* cloneGraph(Node* node) { if(!node) return nullptr; if(mp.count(node)) return mp[node]; // 如果存在,就不用新建了 Node* tmp = new Node(node -> val); mp[node] = tmp; for(int i = ; i < node -> neighbors.size(); ++ i){ if(node -> neighbors[i]) tmp -> neighbors.push_back(cloneGraph(node -> neighbors[i])); } return tmp; } };
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/clone-graph
【LeetCode #207】课程表
现在你总共有 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。这是不可能的。
说明:
输入的先决条件是由边缘列表表示的图形,而不是邻接矩阵。详情请参见图的表示法。 你可以假定输入的先决条件中没有重复的边。
解题思路:
由于本题目中的每个课程之间都有相应的联系,因此我们可以根据课程关系来构建一个有向图,如果在这个有向图中存在一个循环,那么则不能学完所有的课程,因为每个课程都需要每个先决条件的课程。一个很简单的思路是使用拓扑排序算法,可以判断一个循环是否存在于一个有向图中。
拓扑排序算法:计算图中所有节点的入度,如果某些节点的入度为零,则压入到队列todo中,接着循环弹出队列中的节点(即入读为零的节点),同时将下一个节点中入度为零的节点压入队列中,如果最后图都可以分离开,也就在此过程中,每个节点在分离时都可能入度为零。说明这个有向图中没有循环,否则则有循环。
C++代码(拓扑排序):
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) { std::unordered_map<int, int> indegree; for(auto& v : prerequisites) { indegree[v[]]++; } queue<int> que; for(int i=; i<numCourses; ++i) { if(indegree[i] == ) { que.push(i); } } int cnt = ; while(!que.empty()) { int k = que.front(); que.pop(); cnt++; for(auto& v : prerequisites) { if(k == v[]) { if(--indegree[v[]] == ) { que.push(v[]); } } } } if(cnt != numCourses) return false; return true;
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/course-schedule
文章来源:公众号 (算法工程师之路)
完