学习时间:2022-10-3
学习内容
1、leetcode
210. 课程表 II
思路
一道拓扑排序的题目,可以说是很典型,几种情况全部考虑到了。主要需要想到为什么可以用拓扑排序来做的问题
代码
class Solution {
public int[] findOrder(int numCourses, int[][] prerequisites) {
int[] in = new int[numCourses];
LinkedList<Integer> queue = new LinkedList<Integer>();
ArrayList<Integer> ans = new ArrayList<Integer>();
HashMap<Integer,ArrayList<Integer>> edge = new HashMap<Integer,ArrayList<Integer>>();
for(int i = 0;i<prerequisites.length;i++){
//构成一个图
int[] prerequisite = prerequisites[i];
in[prerequisite[0]]++;
ArrayList<Integer> list = edge.getOrDefault(prerequisite[1],new ArrayList<Integer>());
list.add(prerequisite[0]);
edge.put(prerequisite[1],list);
}
for(int i = 0;i<numCourses;i++){
if(in[i] == 0){
queue.add(i);
continue;
}
}
while(!queue.isEmpty()){
int node = queue.poll();
ans.add(node);
ArrayList<Integer> edges = edge.getOrDefault(node,new ArrayList<Integer>());
for(int i = 0;i<edges.size();i++){
int to = edges.get(i);
if(--in[to] == 0){
queue.add(to);
}
}
}
int[] res = new int[ans.size()];
for(int i = 0;i<ans.size();i++){
res[i] = ans.get(i);
}
if(res.length != numCourses) return new int[]{};
return res;
}
}
更优解
一个用时2ms的解法,没有出现在官解上,思路大概一致
class Solution {
int M, N;
int[] e, ne;
int[] he, in;
int idx;
public void add(int a, int b) {
e[idx] = b;
ne[idx] = he[a];
he[a] = idx++;
in[b]++;
}
public void initGraph(int numCourses, int[][] prerequisites) {
M = prerequisites.length;
N = numCourses;
e = new int[M];
ne = new int[M];
he = new int[N];
in = new int[N];
Arrays.fill(he, -1);
for (int[] prerequisite : prerequisites) {
add(prerequisite[1], prerequisite[0]);
}
}
public int[] findOrder(int numCourses, int[][] prerequisites) {
int[] result = new int[numCourses];
// 初始化图
initGraph(numCourses, prerequisites);
// 选出入度为 0 的节点
Queue<Integer> queue = new LinkedList<>();
for (int i = 0; i < numCourses; i++) {
if (in[i] == 0) {
queue.offer(i);
}
}
// 拓扑排序, 保存任意结果
int cnt = 0;
while (!queue.isEmpty()) {
int sz = queue.size();
for (int i = 0; i < sz; i++) {
int t = queue.poll();
result[cnt++] = t;
for (int j = he[t]; j != -1; j = ne[j]) {
if (--in[e[j]] == 0) {
queue.offer(e[j]);
}
}
}
}
return cnt == numCourses ? result : new int[0];
}
}
2、拓扑排序
拓扑排序需要构建一个图,这种排序一般是有向的,需要in和edge,还有一个queue来存当前入队的节点
给定一个包含 n 个节点的有向图 GG,我们给出它的节点编号的一种排列,如果满足:
对于图 G 中的任意一条有向边 (u, v),u 在排列中都出现在 v 的前面。
那么称该排列是图 G 的「拓扑排序」。
经典代码:
queue<int>q;
vector<int>edge[n];
for(int i=0;i<n;i++) //n 节点的总数
if(in[i]==0) q.push(i); //将入度为0的点入队列
vector<int>ans; //ans 为拓扑序列
while(!q.empty())
{
int p=q.front(); q.pop(); // 选一个入度为0的点,出队列
ans.push_back(p);
for(int i=0;i<edge[p].size();i++)
{
int y=edge[p][i];
in[y]--;
if(in[y]==0)
q.push(y);
}
}
if(ans.size()==n)
{
for(int i=0;i<ans.size();i++)
printf( "%d ",ans[i] );
printf("\n");
}
else printf("No Answer!\n"); // ans 中的长度与n不相等,就说明无拓扑序列
————————————————
版权声明:本文为CSDN博主「独-」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_41713256/article/details/80805338
若要求字典序最小,把队列换成优先队列