所有可能路径

力扣第 797 题

输入的图是无环的,不需要visited数组辅助

// 记录所有路径  
List<List<Integer>> res = new LinkedList<>();  

public List<List<Integer>> allPathsSourceTarget(int[][] graph) {  
    LinkedList<Integer> path = new LinkedList<>();  
    traverse(graph, 0, path);  
    return res;  
}  

/* 图的遍历框架 */  
void traverse(int[][] graph, int s, LinkedList<Integer> path) {  

    // 添加节点 s 到路径  
    path.addLast(s);  

    int n = graph.length;  
    if (s == n - 1) {  
    // 到达终点  
    res.add(new LinkedList<>(path));  
    path.removeLast();  
    return;  
    }  

    // 递归每个相邻节点  
    for (int v : graph[s]) {  
    traverse(graph, v, path);  
    }  

    // 从路径移出节点 s  
    path.removeLast();  
}

课程表(有向图中是否存在环)

力扣第 207 题:判断是否能完成所有课程

  • visited数组是用来剪枝的,在代码中是全局变量,并且只赋值true,而没有像onPath一样有回溯操作(即onPath【s】=false),举个例值,有a,b两个节点都有一条到c的路径,那么a判断之后被标记了visited【s】=true,b再去遍历的时候可以直接返回。
  • onPath是记录回溯的路径的,是检查环是否存在的重要标志!

经过测试,只有OnPath没有visited,在100个节点的时候就会超时。

// 记录一次 traverse 递归经过的节点  
boolean[] onPath;  
// 记录遍历过的节点,防止走回头路  
boolean[] visited;  
// 记录图中是否有环  
boolean hasCycle = false;  

boolean canFinish(int numCourses, int[][] prerequisites) {  
    List<Integer>[] graph = buildGraph(numCourses, prerequisites);  

    visited = new boolean[numCourses];  
    onPath = new boolean[numCourses];  

    for (int i = 0; i < numCourses; i++) {  
    // 遍历图中的所有节点  
    traverse(graph, i);  
    }  
    // 只要没有循环依赖可以完成所有课程  
    return !hasCycle;  
}  

void traverse(List<Integer>[] graph, int s) {  
    if (onPath[s]) {  
    // 出现环  
    hasCycle = true;  
    }  

    if (visited[s] || hasCycle) {  
    // 如果之前已经遍历过了,或找到了环,也不用再遍历了  
    return;  
    }  
    // 前序遍历代码位置  
    visited[s] = true;  
    onPath[s] = true;  
    for (int t : graph[s]) {  
    traverse(graph, t);  
    }  
    // 后序遍历代码位置  
    onPath[s] = false;  
}  
List<Integer>[] buildGraph(int numCourses, int[][] prerequisites) {  
    // 图中共有 numCourses 个节点  
    List<Integer>[] graph = new LinkedList[numCourses];  
    for (int i = 0; i < numCourses; i++) {  
    graph[i] = new LinkedList<>();  
    }  
    for (int[] edge : prerequisites) {  
    int from = edge[1];  
    int to = edge[0];  
    // 修完课程 from 才能修课程 to  
    // 在图中添加一条从 from 指向 to 的有向边  
    graph[from].add(to);  
    }  
    return graph;  
}

课程表 II(拓扑排序)

力扣第 210 题:完成所有课程完排的学习顺序

后序遍历的结果进行反转,就是拓扑排序的结果

boolean[] visited;  
// 记录后序遍历结果,存的是to->from,因此要反转  
List<Integer> postorder = new ArrayList<>();  

int[] findOrder(int numCourses, int[][] prerequisites) {  
    // 先保证图中无环  
    if (!canFinish(numCourses, prerequisites)) {  
    return new int[]{};  
    }  
    // 建图  
    List<Integer>[] graph = buildGraph(numCourses, prerequisites);  
    // 进行 DFS 遍历  
    visited = new boolean[numCourses];  
    for (int i = 0; i < numCourses; i++) {  
    traverse(graph, i);  
    }  
    // 将后序遍历结果反转,转化成 int[] 类型  
    Collections.reverse(postorder);  
    int[] res = new int[numCourses];  
    for (int i = 0; i < numCourses; i++) {  
    res[i] = postorder.get(i);  
    }  
    return res;  
}  

void traverse(List<Integer>[] graph, int s) {  
    if (visited[s]) {  
    return;  
    }  

    visited[s] = true;  
    for (int t : graph[s]) {  
    traverse(graph, t);  
    }  
    // 后序遍历位置  
    postorder.add(s);  
}  

// 参考上一题的解法  
boolean canFinish(int numCourses, int[][] prerequisites);  

// 参考前文代码  
List<Integer>[] buildGraph(int numCourses, int[][] prerequisites);

名流问题

力扣第 277 题

所谓「名人」的定义:

1、所有其他人都认识名人。

2、名人不认识任何其他人。

int findCelebrity(int n) {  
    // 先假设 cand 是名人  
    int cand = 0;  
    // 循环一次,两两进行比较,淘汰不可能是名人的人  
    for (int other = 1; other < n; other++) {  
    if (!knows(other, cand) || knows(cand, other)) {  
        // cand 不可能是名人,排除  
        // 假设 other 是名人  
        cand = other;  
    } else {  
        // other 不可能是名人,排除  
        // 什么都不用做,继续假设 cand 是名人  
    }  
    }  

    // 现在的 cand 是排除的最后结果,但不能保证一定是名人  
    for (int other = 0; other < n; other++) {  
    if (cand == other) continue;  
    // 需要保证其他人都认识 cand,且 cand 不认识任何其他人  
    if (!knows(other, cand) || knows(cand, other)) {  
        return -1;  
    }  
    }  

    return cand;  
}
Copyright © qgao 2021-* all right reserved,powered by Gitbook该文件修订时间: 2022-07-08 12:24:46

results matching ""

    No results matching ""