15、指针三剑客之三:图(结合LeetCode 785、210、1059、1135、797学习)(1059、1135需Plus会员)

作者学习算法的教材是LeetCode 101

有需要的同学直接GitHub搜索LeetCode 101即可 **

    一般分为有向(directed)或无向(undirected),有循环(cyclic)或
无循环(acyclic),所有节点相连(connected)或不相连(disconnected)。
    树相当于一个相连的无向无环图。
    常见的图为有向无环图(Directed Acyclic Graph,DAG)

一、二分图

二分图算法也称为染色法,是一种广度优先搜索。如果可以用两种颜色对图中的节点进行着色,并且保证相邻节点的颜色不同,那么图为二分

785. 判断二分图(难度:中等)

  • 利用队列和广度优先搜索,对未染色点进行染色,并检查有无颜色相同的邻接点;
  • 代码如下:
class Solution {
public:
    bool isBipartite(vector<vector<int>>& graph) {
        if(graph.size() == 0) {
            return true;
        }
        queue<int> q;
        vector<int> color(graph.size() , 0);
        for(int i = 0 ; i < graph.size() ; i++) {
            if(!color[i]) {
                q.push(i);
                color[i] = 1;
            }
            while(!q.empty()) {
                int node = q.front();
                q.pop();
                for(const int& j : graph[node]) {//表示遍历graph[node]中的元素,此for循环等同于下面的代码
                    if(color[j] == 0) {
                        q.push(j);
                        color[j] = color[node] == 2 ? 1 : 2;//要与相邻节点颜色不同
                    }
                    else if(color[j] == color[node]) {
                        return false;
                    }
                }
            }
        }
        return true;
    }
};
//等同于上面的for循环,相当于解释上文中的for循环
		for(int j = 0 ; j < graph[node].size() ; j++) {
            if(color[graph[node][j]] == 0) {
                q.push(graph[node][j]);
                color[graph[node][j]] = color[node] == 2 ? 1 : 2;//要与相邻节点颜色不同
            }
            else if(color[graph[node][j]] == color[node]) {
                return false;
            }
        }

210. 课程表Ⅱ(难度:中等)

  • 首先用graph构造一个邻接矩阵,方便查找,接着用indegree数组记录每个节点的入度,res记录图的拓扑排序;
  • 用队列实现广度优先搜索,最后判断如果res中的元素个数不等于总数numCourses,说明图中存在闭环,无法学习到所有课程,否则返回拓扑排序res,按照res的顺序可以学习完所有课程;
  • 代码如下:
class Solution {
public:
    vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
        vector<vector<int>> graph(numCourses , vector<int>());
        vector<int> indegree(numCourses , 0) , res;
        for(const auto& prerequisites : prerequisites) {
            graph[prerequisites[1]].push_back(prerequisites[0]);
            indegree[prerequisites[0]]++;
        }
        queue<int> q;
        for(int i = 0 ; i < indegree.size() ; i++) {
            if(indegree[i] == 0) {
                q.push(i);
            }
        }
        while(!q.empty()) {
            int u = q.front();
            q.pop();
            res.push_back(u);
            for(auto v : graph[u]) {
                indegree[v]--;
                if(indegree[v] == 0) {
                    q.push(v);
                }
            }
        }
        if(res.size() != numCourses) {
            return vector<int>();
        }
        return res;
    }
};

1059. 从始点到终点的所有路径(难度:中等)(需Plus会员)

  • 利用队列和广度
  • 代码如下:

1135. 最低成本联通所有城市(难度:中等)

  • 利用队列和广度
  • 代码如下:

797. 所有可能的路径(难度:中等)

  • 常规的深度优先遍历算法;
  • 代码如下:
class Solution {
    vector<int> temp;
    vector<vector<int>> res;
public:
    vector<vector<int>> allPathsSourceTarget(vector<vector<int>>& graph) {
        temp.push_back(0);
        DFS(graph , 0);
        return res;
    }
    void DFS(vector<vector<int>>& graph , int k) {
        if(k == graph.size() - 1) {
            res.push_back(temp);
        }
        for(const int a : graph[k]) {
            temp.push_back(a);
            DFS(graph , a);
            temp.pop_back();
        }
    }
};

你可能感兴趣的:(LeetCode,算法)