算法系列--BFS解决拓扑排序

news2024/11/20 7:00:41

💕"请努力活下去"💕
作者:Lvzi
文章主要内容:算法系列–算法系列–BFS解决拓扑排序
在这里插入图片描述

大家好,今天为大家带来的是算法系列--BFS解决拓扑排序

前言:什么是拓扑排序
拓扑排序–解决有顺序的排序问题(要做事情的先后顺序)
在这里插入图片描述
几个基本概念

  1. 有向无环图:有方向,但是不存在环路
  2. 入度:有多少条路可以走到当前节点
  3. 出度:从当前节点出发,有多少条线路

拓扑排序问题的思路比较固定,难点在于灵活的采用不同的容器去建图和表示每个节点的入度信息,下面是拓扑排序问题的步骤:

Step1:建图

建立一个有向图来表示做事情的先后顺序

如何建图–灵活使用语言提供的容器

要存储的是:一个节点与其所相连的节点(边),两点构成一条线段
建立映射关系:
–哈希表存储
Map<Point,List< Point >>

表示每一个节点的入度:
我们是根据入度是否为0来决定先后顺序的

一个节点的入度就是有多少个指向该节点的边

使用数组int[] in表示

在这里插入图片描述

Step2.进行拓扑排序(队列 + bfs)

  1. 将所有入度为0的节点添加进队列
    在这里插入图片描述

  2. 循环队列

    • 获取头结点t,将t添加进入最后的结果之中(如果要表示的话)
    • 将与t相连的边删除–等价于将与t相连的点的入度减1
    • 判断与t相连的点的入度是否为0,如果为0,表示是新的起点,添加进队列之中
  3. 直到图中没有节点或者没有入度为0的节点(有环)
    在这里插入图片描述

注意有环的情况
在这里插入图片描述

一.课程表

题目链接:课程表
在这里插入图片描述

分析:

拓扑排序

  • 如果最后存在入度不为0的点–证明有环–无法按照p数组的顺序完成课程
  • 全为0,证明可以完成所有课程

代码:

class Solution {// 本题节点就是所有的可成
    public boolean canFinish(int n, int[][] p) {
        // 1.建图
        Map<Integer,List<Integer>> edges = new HashMap<>();
        int[] in = new int[n];

        for(int i = 0; i < p.length; i++) {
            int a = p[i][0], b = p[i][1];// b->a
            if(!edges.containsKey(b)) // 处理为空
                edges.put(b,new ArrayList<>());
            edges.get(b).add(a); // 建立关系
            in[a]++;// 入度加1
        }

        // 2.拓扑排序
        Queue<Integer> q = new LinkedList<>();
        for(int i = 0; i < n; i++)// 将所有入度为0的点添加进入队列
            if(in[i] == 0)
                q.add(i);

        // bfs
        // 得到对头元素 -- 删除与其相连的边 -- 找到下一个起始位置
        while(!q.isEmpty()) {
            int t = q.poll();
            for(int i : edges.getOrDefault(t,new ArrayList<>())) {// 将与t相连的点的入度减1
                in[i]--;
                if(in[i] == 0) q.add(i);// 如果入度为0,表示新的起点,添加进队列
            }
        }

        // 判断是否存在入度不为0 的点,如果存在,证明有环,则无法完成所有课程,返回false
        for(int i : in)
            if(i != 0) 
                return false;

        return true;
    }
}

总结:

  1. 注意本题p数组的指向,是b指向a
  2. 大致的过程很简单
    • 建图:建立点与点之间的联系(Map),统计所有点的入度情况–循环遍历即可
    • 拓扑排序:先将所有入度为0的点添加进入队列(起点),bfs循环遍历
  3. 一定要注意我们建的图可能有环,也可能无环,如果有环,最后图中一定有入度不为0的节点

二.课程表II

题目链接:课程表II
在这里插入图片描述

分析:

和上一道题目相同 只需记录排序结果即可

代码:

import java.util.Collections;
class Solution {
    public int[] findOrder(int n, int[][] p) {
        // 1.建图
        Map<Integer,List<Integer>> edges = new HashMap<>();
        int[] in = new int[n];

        for(int i = 0; i < p.length; i++) {
            int a = p[i][0], b = p[i][1];// b->a
            if(!edges.containsKey(b)) // 处理为空
                edges.put(b,new ArrayList<>());
            edges.get(b).add(a); 
            in[a]++;// 入度加1
        }

        // 2.拓扑排序
        Queue<Integer> q = new LinkedList<>();
        for(int i = 0; i < n; i++)// 将所有入度为0的点添加进入队列
            if(in[i] == 0)
                q.add(i);

        int[] ret = new int[n];
        int index = 0;
        // bfs
        while(!q.isEmpty()) {
            int t = q.poll();
            ret[index++] = t;
            for(int i : edges.getOrDefault(t,new ArrayList<>())) {// 将与t相连的点的入度减1
                in[i]--;
                if(in[i] == 0) q.add(i);// 如果入度为0,表示新的起点,添加进队列
            }
        }

        return index == n ? ret : new int[]{};
    }
}

三.⽕星词典

题目链接:⽕星词典
在这里插入图片描述

分析:

这里面的节点就是一个一个字符,题目最终要求的是字符的先后顺序–拓扑排序
三步:建图,拓扑排序,判断

在这里插入图片描述

代码:

class Solution {
    Map<Character,List<Character>> edges = new HashMap<>();// 建图使用
    Map<Character,Integer> in = new HashMap<>();// 统计每一个节点的入度信息

    public String alienOrder(String[] words) {
        // 初始化入度信息
        for(String str : words)
            for(int i = 0; i < str.length(); i++)
                in.put(str.charAt(i),0);

        // 建图  使用两层for循环来搜集信息
        int n = words.length;
        for(int i = 0; i < n - 1; i++) {
            for(int j = i + 1; j < n; j++) {
                String s1 = words[i], s2 = words[j];
                int len = Math.min(s1.length(),s2.length()), index = 0;
                while(index < len && s1.charAt(index) == s2.charAt(index))
                    index++;
				// 处理不合法的情况  s1 = abc  s2 = ab
                if(index == s2.length() && index < s1.length()) return "";
                // 走到两个字符串不相同的字母
                if(index >= len) continue;// 防止越界
                char prev = s1.charAt(index), behind = s2.charAt(index);
                if(!edges.containsKey(prev))
                    edges.put(prev,new ArrayList<>());
    
                if(!edges.get(prev).contains(behind)) {// 这里不加if判断也行,加了是为了减少冗余信息的加入
                    edges.get(prev).add(behind);
                    in.put(behind,in.get(behind) + 1);
                }
            }
        }

        // 2.拓扑排序
        StringBuffer ret = new StringBuffer();
        Queue<Character> q = new LinkedList<>();
        for(char ch : in.keySet()) // 将度为0的节点添加进队列之中
            if(in.get(ch) == 0) q.add(ch);

        while(!q.isEmpty()) {
            char t = q.poll();
            ret.append(t);
            // 遍历相连的点
            for(char ch : edges.getOrDefault(t,new ArrayList<>())) {
                in.put(ch,in.get(ch) - 1);
                if(in.get(ch) == 0) q.add(ch);
            }
        }

        // 判断是否存在入度不为0的点
        for(char ch : in.keySet()) 
            if(in.get(ch) != 0) return "";

        return ret.toString();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1661721.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

3D技术成为电商流量密码,如何提高商品转化率?

随着互联网技术的飞速发展和Web3.0时代的到来&#xff0c;消费者的购物体验需求也在经历着前所未有的变革。从传统的线下购物到线上网站&#xff0c;再到直播带货等多元化消费形式的涌现&#xff0c;消费者对产品展示形式的视觉冲击力要求日益提升。 在这一背景下&#xff0c;3…

django中的日志处理

1、事件追踪 在什么样的时间发生了什么样的事情 2、bug调试 3、程序告警 4、大数据统计 ELK 日志分析系统 elasticsearh logstasn kibana 名词概念 loggers&#xff1a;日志器 —— 定大方向&#xff1a;1 handlers&#xff1a;处理器 —— 执行:3 formatters&#xff…

车载电子电器架构 —— 应用软件开发(上)

车载电子电器架构 —— 应用软件开发(上) 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明…

c++:(map和set的底层简单版本,红黑树和AVL树的基础) 二叉搜索树(BST)底层和模拟实现

文章目录 二叉搜索树的概念二叉搜索树的操作二叉搜索树的查找find 二叉搜索树的模拟实现构造节点insertfinderase(细节巨多,面试可能会考)a.叶子节点b.有一个孩子左孩子右孩子 c.有两个孩子注意: erase代码 中序遍历 二叉搜索树的应用k模型k模型模拟实现的总代码 k-value模型k-…

fb设备驱动框架分析

一、字符设备注册过程&#xff1a; 归根到底&#xff0c;fb设备也是一个字符设备&#xff0c;所以逃不开常规的字符设备驱动框架&#xff1a; Linux内核中编写字符设备驱动通常遵循以下步骤&#xff1a; ①、定义主设备号&#xff1a; 在Linux中&#xff0c;每个字符设备都…

第十五届蓝桥杯python B组省赛

前言&#xff1a; 这是我第一次参加蓝桥杯&#xff0c;成绩并不理想&#xff0c;我反思了一下午&#xff0c;我的问题主要是知识点学不透&#xff0c;题目做的太少&#xff0c;而且学习的时候少数时间不专心&#xff0c;但是&#xff0c;我能感觉到我的学习能力并不弱&#xf…

Unity TileMap入门

概述 相信很多同学学习制作游戏都是从2D游戏开始制作的吧&#xff0c;瓦片地图相信大家都有接触&#xff0c;那接下来让我们学习一下这部分的内容吧&#xff01; Tilemap AnimationFrameRate:设置每帧动画的播放速率。Color:瓦片地图的颜色TileAnchor:锚点&#xff0c;&#x…

AI英语口语训练软件有哪些?这4款简单易用

AI英语口语训练软件有哪些&#xff1f;AI英语口语训练软件在现代语言学习中确实扮演着举足轻重的角色。它们凭借先进的智能算法&#xff0c;能够为我们量身定制学习方案&#xff0c;精准识别并纠正发音错误&#xff0c;模拟真实对话场景&#xff0c;使学习过程更加高效、有趣。…

Qt复习第二天

1、菜单栏工具栏状态栏 #include "mainwindow.h" #include "ui_mainwindow.h" #pragma execution_character_set("utf-8"); MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this);//菜…

【C++】转换构造函数和类型转换函数

目录 转换构造函数转换构造函数调用 类型转换函数类型转换函数定义形式应用 转换构造函数 转换构造函数就是一种构造函数&#xff0c;将一个其他类型的数据转换成一个类的对象的构造函数。 类型->类对象 转换构造函数调用 &#xff08;1&#xff09;显式强制类型转换&…

抽象类基本概念

抽象类及抽象方法 概念&#xff1a;一个类中没有包含足够的信息来描绘一个具体的对象&#xff0c;这种类被定义为抽象类&#xff0c;含有抽象方法的类也被称为抽象类。 用通俗的话来说就是当一个类的某个功能&#xff08;方法&#xff09;实现不确定时&#xff0c;我们就将该…

数据挖掘(二)数据预处理

前言 基于国防科技大学 丁兆云老师的《数据挖掘》 数据挖掘 数据挖掘&#xff08;一&#xff09;数据类型与统计 2、数据预处理 2.1数据清理 缺失值处理&#xff1a; from sklearn.impute import SimpleImputer# 创建一个SimpleImputer对象&#xff0c;指定缺失值的处理策略…

信息系统项目管理基础

目录 一、项目管理概论 1、定义 2、项目管理的十二原则 3、SMART原则 4、项目经理 5、项目的生命周期 二、项目立项管理 1、项目启动过程 三、项目整合管理 1、管理基础 2、项目整合管理过程 ①制定项目章程 ②制定项目管理计划 ③指导与管理项目工作 ④管理项目…

【算法与数据结构】数组

文章目录 前言数组数组的定义数组的基本操作增加元素删除元素修改元素查找元素 C STL 中的数组arrayvector Python3 中的列表访问更改元素值遍历列表检查列表中是否存在某元素增加元素删除元素拷贝列表总结 Python3 列表的常用操作 参考资料写在最后 前言 本系列专注更新基本数…

计算机系列之数据库技术

13、数据库技术&#xff08;重点、考点&#xff09; 1、三级模式-两级映像&#xff08;考点&#xff09; 内模式&#xff1a;管理如何存储物理的数据&#xff0c;对应具体物理存储文件。 **模式&#xff1a;**又称为概念模式&#xff0c;就是我们通常使用的基本表&#xff0c…

AI算法-高数3-导数-求导法则

P16 2.2 求导法则&#xff0c;宋浩老师&#xff1a;2.2 求导法则_哔哩哔哩_bilibili 反函数求导法则&#xff1a; 复合函数求导&#xff1a;剥洋葱法。

H5 鼠标点击粒子扩散效果

&#x1f9d0;别人的博客中有这样的效果&#xff0c;于是自己就尝试实现了一下。 效果如图 源码如下 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content&quo…

一文彻底读懂信息安全等级保护:包含等保标准、等保概念、等保对象、等保流程及等保方案(附:等保相关标准文档)

1. 什么是等级保护&#xff1f; 1.1. 概念 信息安全等级保护是指根据我国《信息安全等级保护管理办法》的规定&#xff0c;对各类信息系统按照其重要程度和保密需求进行分级&#xff0c;并制定相应的技术和管理措施&#xff0c;确保信息系统的安全性、完整性、可用性。根据等…

CTFHUB-技能树-Web题-RCE(远程代码执行)-文件包含

CTFHUB-技能树-Web题-RCE&#xff08;远程代码执行&#xff09; 文件包含 文章目录 CTFHUB-技能树-Web题-RCE&#xff08;远程代码执行&#xff09;文件包含解题方法1:![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/71f7355b3c124dfe8cdf1c95e6991553.png#pic_ce…

Docker快速搭建NAS服务——NextCloud

Docker快速搭建NAS服务——NextCloud 文章目录 前言NextCloud的搭建docker-compose文件编写运行及访问 总结 前言 本文主要讲解如何使用docker在本地快速搭建NAS服务&#xff0c;这里主要写如下两种&#xff1a; FileBrowser1&#xff1a;是一个开源的Web文件管理器&#xff…