785. 判断二分图-7月16日

题目

785. 判断二分图

785. 判断二分图-7月16日

 

 

 

我的思路

我自己做的方法对于简单测试用例可行,但提交后遇到大的测试用例因为复杂度过高无法运行。

我的思路是这样:实质上就是找一种分类A和B:i属于A时,若j属于B,graph[i]中一定没有j;反之亦然

整理一下思路:
递归的出口条件:遍历完最后一个节点i=graph.length or 两个集合中存在重复元素
check(int i,vector<vector<int>>& graph,vector<int> A,vector<int> B,int type)递归函数内部的执行过程:
0.如果i等于graph.length,那么返回true
1.把i加入A,把graph[i]中所有元素加入B
2.判断A和B中是否有重复元素,若有返回false
3.bool R1 = check(graph,A,B,0)
4.bool R2 = check(graph,A,B,1)
5.return R1 || R2
时间复杂度:2^n,因为是递归且递归函数中有两个递归调用

我的实现

class Solution {
public:
    bool isBipartite(vector<vector<int>>& graph) {
        set<int> A,B;
        return check(0,graph,A,B,0);
    }
    bool check(int i,vector<vector<int>>& graph,set<int> A,set<int> B,int type){
        if(i==graph.size()) return true;//0.如果i等于graph.length,那么返回true
        if(type == 0){//1.把i加入A,把graph[i]中所有元素加入B
            A.insert(i);
            for(auto iter : graph[i])   B.insert(iter);
        }else{
            B.insert(i);
            for(auto iter : graph[i])   A.insert(iter);
        }
        for(auto iter: A){//2.判断A和B中是否有重复元素,若有返回false
            if(B.count(iter)>0) return false;
        }
        bool R1 = check(i+1,graph,A,B,0);
        if(R1==true)return true;
        bool R2 = check(i+1,graph,A,B,1);
        return R1 || R2;

    }

};
/**
重新整理一下思路:
递归的出口条件:遍历完最后一个节点i=graph.length or 两个集合中存在重复元素
check(int i,vector<vector<int>>& graph,vector<int> A,vector<int> B,int type)递归函数内部的执行过程:
0.如果i等于graph.length,那么返回true
1.把i加入A,把graph[i]中所有元素加入B
2.判断A和B中是否有重复元素,若有返回false
3.bool R1 = check(graph,A,B,0)
4.bool R2 = check(graph,A,B,1)
5.return R1 || R2
*/

/**
实质上就是找一种分类A和B:
i属于A时,若j属于B,graph[i]中一定没有j;反之亦然
1.强行暴力枚举所有分类的话,时间复杂度会达到2^n以上
2.遍历graph,对每个graph[i],可以产生两种结果: 
    graph[i]中的元素属于A,i属于B    or     graph[i]中的元素属于B,i属于A
    接着检查是否与现有集合有冲突,若没有则继续,若有则返回
*/

时间复杂度过大!换思路

class Solution {
public:
    bool isBipartite(vector<vector<int>>& graph) {
        int constexpr NOCOLOR=0;
        int constexpr RED=1;
        int constexpr GREEN=2;
        int numofNodes=graph.size();
        vector<int> nodestocheck;
        vector<int> colors(numofNodes,NOCOLOR);
        //colors[0]=RED;
        //nodestocheck.push_back(0);
        for(int i=0;i<numofNodes;i++){
            if(colors[i]!=NOCOLOR)continue;
            colors[i]=RED;
            printf("%dinn",i);
            nodestocheck.push_back(i);
            while(!nodestocheck.empty()){
                int presentNode = *nodestocheck.begin();
                nodestocheck.erase(nodestocheck.begin());
                printf("%doutn",presentNode);
                for(auto iter:graph[presentNode]){
                    if(colors[iter]==colors[presentNode]){
                        //printf("%d:%d:%d",colors[iter],iter,presentNode);
                        return false;
                    }else
                    if(colors[iter]==NOCOLOR){
                        colors[iter]= colors[presentNode]==RED?GREEN:RED;
                        nodestocheck.push_back(iter);
                        printf("%dinn",iter);
                    }
                }
            }
        }
        return true;
    }

};

以上是我的广搜实现

拓展学习

constexpr

https://blog.csdn.net/u011469662/article/details/96866034

语义上:
constexpr:告诉编译器我可以是编译期间可知的,尽情的优化我吧。
const:告诉程序员没人动得了我,放心的把我传出去;或者放心的把变量交给我,我啥也不动就瞅瞅。

语法上:
constexpr是一种比const 更严格的束缚, 它修饰的表达式本身在编译期间可知, 并且编译器会尽可能的 evaluate at compile time. 在constexpr 出现之前, 可以在编译期初始化的const都是implicit constexpr. 直到c++ 11, constexpr才从const中细分出来成为一个关键字, 而 const从1983年 c++ 刚改名的时候就存在了… 如果你初学c++, 应当尽可能的, 合理的使用constexpr来帮助编译器优化代码.

深度优先搜索

class Solution {
private:
    static constexpr int UNCOLORED = 0;
    static constexpr int RED = 1;
    static constexpr int GREEN = 2;
    vector<int> color;
    bool valid;

public:
    void dfs(int node, int c, const vector<vector<int>>& graph) {
        color[node] = c;
        int cNei = (c == RED ? GREEN : RED);
        for (int neighbor: graph[node]) {
            if (color[neighbor] == UNCOLORED) {
                dfs(neighbor, cNei, graph);
                if (!valid) {
                    return;
                }
            }
            else if (color[neighbor] != cNei) {
                valid = false;
                return;
            }
        }
    }

    bool isBipartite(vector<vector<int>>& graph) {
        int n = graph.size();
        valid = true;
        color.assign(n, UNCOLORED);
        for (int i = 0; i < n && valid; ++i) {
            if (color[i] == UNCOLORED) {
                dfs(i, RED, graph);
            }
        }
        return valid;
    }
};

时间复杂度:O(N+M)O(N+M),其中 NN 和 MM 分别是无向图中的点数和边数。

空间复杂度:O(N)O(N),存储节点颜色的数组需要 O(N)O(N) 的空间,并且在深度优先搜索的过程中,栈的深度最大为 NN,需要 O(N)O(N) 的空间。

转自leetcode官方题解

广度优先搜索

class Solution {
private:
    static constexpr int UNCOLORED = 0;
    static constexpr int RED = 1;
    static constexpr int GREEN = 2;
    vector<int> color;

public:
    bool isBipartite(vector<vector<int>>& graph) {
        int n = graph.size();
        vector<int> color(n, UNCOLORED);
        for (int i = 0; i < n; ++i) {
            if (color[i] == UNCOLORED) {
                queue<int> q;
                q.push(i);
                color[i] = RED;
                while (!q.empty()) {
                    int node = q.front();
                    int cNei = (color[node] == RED ? GREEN : RED);
                    q.pop();
                    for (int neighbor: graph[node]) {
                        if (color[neighbor] == UNCOLORED) {
                            q.push(neighbor);
                            color[neighbor] = cNei;
                        }
                        else if (color[neighbor] != cNei) {
                            return false;
                        }
                    }
                }
            }
        }
        return true;
    }
};

时间复杂度:O(N+M)O(N+M),其中 NN 和 MM 分别是无向图中的点数和边数。

空间复杂度:O(N)O(N),存储节点颜色的数组需要 O(N)O(N) 的空间,并且在广度优先搜索的过程中,队列中最多有 N-1N−1 个节点,需要 O(N)O(N) 的空间。

转自leetcode官方题解

 

原文链接: https://www.cnblogs.com/BoysCryToo/p/13321832.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    785. 判断二分图-7月16日

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/367116

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 下午5:28
下一篇 2023年3月2日 下午5:29

相关推荐