leetcode-8:DFS和BFS

DFS和BFS

节点间通路

节点间通路。给定有向图,设计一个算法,找出两个节点之间是否存在一条路径。

提示:

节点数量n在[0, 1e5]范围内。
节点编号大于等于 0 小于 n。
图中可能存在自环和平行边。

思路: 判断两点之间是否连通,用DFS或者BFS,用栈实现DFS,用队列实现BFS。我不喜欢递归,递归要迭代,我脑子里建不起迭代的过程图。

用栈实现DFS伪码:

  1. 栈初始化,并让起始顶点入栈,起始顶点改为已访问

  2. 栈不为空:

    2.1 取栈顶元素
    2.2 栈顶元素的邻接点 n n n,并且 n n n没有被访问,则:将邻接点 n n n标记为已访问,并且让点 n n n进栈
    2.3 如果2.2没有邻接点进展,需要将当前结点退栈。

class Solution {
public:
    vector> construct_map(int n, vector>& graph){
        vector> map(n);
        int row = graph.size();
        for(int i = 0;i>& graph, int start, int target) {
        if(start == target) return true;
        vector> map = construct_map(n, graph);
        // 
        vector visit(n, 0);
        stack S;
        S.push(start);
        visit[start] = 1;
        while(!S.empty()){
            int tmp = S.top();
            int len = map[tmp].size();
            bool flag = false;
            for(int i=0;i>& graph, int start, int target) {
        if(start == target) return true;
        vector> map = construct_map(n, graph);
        // 
        vector visit(n, 0);
        queue Q;
        Q.push(start);
        visit[start] = 1;
        while(!Q.empty()){
            int tmp = Q.front();
            int len = map[tmp].size();
            bool flag = false;
            for(int i=0;i

判断二分图

给定一个无向图graph,当这个图为二分图时返回true。

如果我们能将一个图的节点集合分割成两个独立的子集A和B,并使图中的每一条边的两个节点一个来自A集合,一个来自B集合,我们就将这个图称为二分图。

graph将会以邻接表方式给出,graph[i]表示图中与节点i相连的所有节点。每个节点都是一个在0到graph.length-1之间的整数。这图中没有自环和平行边: graph[i] 中不存在i,并且graph[i]中没有重复的值。

思路: 二分图染色法判定二分图。对一个无向图,要给每个图上顶点进行染色,最多用两种染色,任意相邻的顶点染色不同,如果可以对图进行染色,那就说明是一个二分图。题目中没说给给定的图是连通图,所以还需要考虑到非连通的图。

class Solution {
public:
    bool isBipartite(vector>& graph) {
        int n = graph.size();
        stack S;
        vector vis(n, 0);
        vector color(n, -1);
        // 考虑图非连通
        for(int i=0;i

课程表

现在你总共有 n 门课需要选,记为 0 到 n-1。

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

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

思路: 判断是否是有向无环图DAG。DAG才有拓扑排序,非DAG没有拓扑排序。使用顶点入度+BFS,判断是否能够拓扑排序。

class Solution {
public:
    bool canFinish(int numCourses, vector>& prerequisites) {
        int row = prerequisites.size();
        vector degree(numCourses, 0);
        for(int i=0;i Q;
        for(int i=0;i

不同路径

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。

问总共有多少条不同的路径?

思路: 假设网格的大小为 n ∗ m n*m nm,规定只能向下或者向右,从网格的左上角到右下角需要走 n + m − 2 n+m-2 n+m2步,其中向下走了 n − 1 n-1 n1,向右走了 m − 1 m-1 m1,所以总的路径数就是 C m + n − 2 m i n ( n , m ) − 1 C_{m+n-2}^{min(n,m)-1} Cm+n2min(n,m)1

求组合数用到了 C n m = C n − 1 m − 1 + C n − 1 m C_{n}^{m} = C_{n-1}^{m-1} + C_{n-1}^{m} Cnm=Cn1m1+Cn1m

class Solution {
public:
    int uniquePaths(int m, int n) {
        int total = m + n - 2;
        int select = min(m, n) - 1;
        return combination(total, select);
    }
    int combination(int total, int select){
        if(total==select||select==0){
            return 1;
        }else if(select == 1){
            return total;
        }
        return combination(total-1, select-1) + combination(total-1, select);
    }
};

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

你可能感兴趣的:(leetcode,数据结构)