leetcode判断二分图

news/2024/7/16 7:54:34 标签: leetcode, 算法, 职场和发展

判断二分图

图的问题肯定要用到深度优先遍历或者广度优先遍历,但又不是单纯的深度优先遍历算法和广度优先遍历算法,而是需要在遍历的过程中加入与解决题目相关的逻辑。

题干中说了,这个图可能不是连通图,这个提示有什么作用呢?

很多时候我们接触的题目,图都是连通的,对于连通图来说,从一个点开始遍历,不管是深度优先还是广度优先,遍历一遍就可以把图中的所有点都遍历到;而对于非连通图来说,从一个点开始遍历,就无法将所有点都遍历一遍,这就需要针对每个点都进行一次遍历。


不管使用深度优先遍历算法还是使用广度优先遍历算法,都要实时记录结果,如果当前已经确定了不是连通图,那么说明结果已经确定了,就不需要继续判断,直接返回就可以。因为已经判断不是连通图,那么再继续判断下去没有意义,不是连通图的情况已经确定;如果在判断过程中,一直是连通图,那么还有没有遍历到的点,还是需要继续遍历的,因为剩下的点可能是不连通的。

1 深度优先遍历算法

class Solution {
public:
    enum Color {
        kUnColored = 0,
        kRed = 1,
        kGreen = 2
    };
    // 如果已经确定不是连通图了,就不需要继续遍历了
    bool isBipartite(vector<vector<int>>& graph) {
      int size = graph.size();
      // 图可能是非连通图,所以需要从每个节点开始进行一次遍历
      for (int i = 0; i < size && result == true; i++) {
        // 如果这个点没有遍历到,那么才需要遍历,已经遍历到的不需要继续遍历
        if (dataColor[i] == Color::kUnColored) {
          dfsScanGraph(graph, i, Color::kRed);
        }
      }
      return result;
    }

    void dfsScanGraph(vector<vector<int>> &graph, int const node, Color const color) {
       if (result == false) {
           return;
       }
       dataColor[node] = color;
       const Color line_color{color == Color::kRed ? Color::kGreen : Color::kRed};
       
       //给node连接的这一行的节点染色
       for (int data : graph[node]) {
         if (result == false) {
            return;
         }
         // 1、如果与node颜色相同,那么这两者属于同一个区域,可以确定不是二分图
         // 2、如果这个点还没有染色,那么进行递归染色,颜色与node不同的颜色
         // 3、如果节点已经染色,并且与node颜色不同,那么不做处理
         if (dataColor[data] == color) {
            result = false;
            return;
         } else if (dataColor[data] == Color::kUnColored){
            dfsScanGraph(graph, data, line_color);  
         }
       }
    }

private:
  int dataColor[101] = {0};
  bool result = true;
};

2 广度优先遍历算法

class Solution {
public:
    enum Color {
        kUnColored = 0,
        kRed = 1,
        kGreen = 2
    };

    bool isBipartite(vector<vector<int>>& graph) {
      int size = graph.size();
      for (int i = 0; i < size && result == true; i++) {
          if (dataColor[i] == Color::kUnColored) {
              // 广度优先遍历需要使用一个队列来辅助
              // 每一次广度优先遍历,都使用一个新的,空的队列
              std::queue<int> queue;
              bfsScanGraph(graph, i, Color::kRed, queue);
          }
      }
      return result;
    }

    void bfsScanGraph(vector<vector<int>> &graph, int const data, Color const color,std::queue<int> &queue) {
        if (result == false) {
            return;
        }

        dataColor[data] = color;
        queue.push(data);

        
        while (!queue.empty()) {
            int head_data = queue.front();
            queue.pop();
            const Color another_color{dataColor[head_data] == Color::kRed ? Color::kGreen : Color::kRed};

            for (int line_data : graph[head_data]) {
                if (result == false) {
                    return;
                }

                if (dataColor[line_data] == Color::kUnColored) {
                    dataColor[line_data] = another_color;
                    queue.push(line_data);
                } else {
                    // 这里比较的对象与深度优先遍历中比较的是不一样的
                    // 深度优先比较的对象是node,广度优先比较的对象是出队的head_data
                    // 两者的相同点,比较的对象都是与这一行的行首进行比较,行首表示这与当前这个节点是临接点
                    if (dataColor[line_data] == dataColor[head_data]) {
                        result = false;
                        return;
                    }
                }
            }

        }
    }

private:
  int dataColor[101] = {0};
  bool result = true;
};


http://www.niftyadmin.cn/n/5543009.html

相关文章

四、(1)网络爬虫入门及准备工作(爬虫及数据可视化)

四、&#xff08;1&#xff09;网络爬虫入门及准备工作&#xff08;爬虫及数据可视化&#xff09; 1&#xff0c;网络爬虫入门1.1 百度指数1.2 天眼查1.3 爬虫原理1.4 搜索引擎原理 2&#xff0c;准备工作2.1 分析爬取页面2.2 爬虫拿到的不仅是网页还是网页的源代码2.3 爬虫就是…

【MySQL基础篇】多表查询

1、多表关系 概述&#xff1a;项目开发中&#xff0c;在进行数据库表结构操作设计时&#xff0c;会根据业务需求及业务模板之间的关系&#xff0c;分析并设计表结构&#xff0c;由于业务之间相互关联&#xff0c;所以各个表结构之间也存在着各种联系&#xff0c;基本上分为三种…

免杀笔记 ----> DLL注入

这段时间我们暂时没什么事情干的话我们就继续更新我们的免杀笔记力&#xff01;&#xff01;&#xff01; &#xff1a;今天我们讲DLL注入 目录 1.DLL注入 2.直接加载DLL&#xff1f; 3.远程线程注入 获取Handle 远程申请内存空间 将我们的CS的DLL加载入内存 创建远程线…

Android - SIP 协议

SIP 代表(会话发起协议)。 它是一种协议&#xff0c;可让应用程序轻松设置呼出和呼入语音呼叫&#xff0c;而无需直接管理会话、传输级通信或音频记录或回放。 SIP 应用程序 SIP 的一些常见应用是。 视频会议即时消息 开发要求 以下是开发 SIP 应用程序的要求 − Android 操作系…

Pytorch中分类回归常用的损失和优化器

Pytorch中分类回归常用的损失和优化器 在机器学习和深度学习中&#xff0c;分类任务和预测任务&#xff08;回归任务&#xff09;有不同的常用损失函数和优化器。下面将详细介绍这些常用的损失函数和优化器。 分类任务 1. 损失函数 交叉熵损失&#xff08;Cross-Entropy Los…

大模型LLM面试常见算法题-包括Attention和Transformer常见面试题

大模型&#xff1a; 位置编码有哪些&#xff1f; 介绍LoRA与QLoRA RAG和微调的区别是什么&#xff1f; 哪些因素会导致LLM的偏见&#xff1f; 什么是思维链&#xff08;CoT&#xff09;提示&#xff1f; Tokenizer的实现方法及原理 解释一下大模型的涌现能力&#xff1f;…

何为vue脚手架?

一. vue脚手架的基本知识 1. Vue脚手架是什么&#xff1f; ① Vue脚手架&#xff0c;也称为Vue CLI或vue-cli&#xff08;Command Line Interface&#xff09;&#xff1b;② Vue脚手架是一个基于Vue.js的快速生成项目股价的工具&#xff0c;它可以帮助开发者快速搭建一个带有r…

Unity3D游戏 RPG

丛林探险游戏 人物进行探险游戏 拥有登录&#xff0c;首页&#xff0c;3D物体旋转浏览的功能&#xff0c;还能进行种植树等功能