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

💕"请努力活下去"💕
作者: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();
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Vulntarget-a 打靶练习

关于环境配置&#xff0c;这里就不在附上图片和说明了&#xff0c;网上一大堆&#xff0c;这里只针对自己练习&#xff0c;做一个记录。 外网信息收集 利用arpscan工具&#xff0c;扫描了当前局域网中都存在哪些主机&#xff1a; 正常来说我们不应该使用arpscan&#xff0c;而是…

各个硬件的工作原理

目录 前言 主存储器的基本组成 运算器的基本组成 控制器的基本组成 计算机的工作过程 前言 上个小节我们学习了现代计算机的基本构成都是基于冯诺依曼的思想来设计的,那么本章节要来看看主机内部三个组件的细节以及它们之间相互协调工作的. 主存储器的基本组成 这张图非常…

WPF基础应用

WPF参考原文 MVVM介绍 1.常用布局控件 1.1 布局控件 WPF&#xff08;Windows Presentation Foundation&#xff09;提供了多种布局容器来帮助开发者设计用户界面&#xff0c;以下是一些常用的布局&#xff1a; Grid: Grid是最常用的布局容器之一&#xff0c;它允许你通过定…

暗区突围端游海外版|暗区突围怎么玩 新手游玩攻略分享

游戏中健康系统与其它射击游戏有很大区别&#xff0c;根据受伤部位、伤势的不同&#xff0c;会有不同的表现。除了头部之外&#xff0c;其它部位如果损坏后继续受到伤害&#xff0c;那么伤害将会分摊到身体其它部位。在暗区内或者暗区外都可以对角色进行治疗&#xff0c;角色不…

Mybatis进阶(映射关系一对一 )

文章目录 1.基本介绍1.基本说明2.映射方式 2.配置xml方式&#xff08;多表联查&#xff09;1.数据库表设计2.新建子模块1.创建子模块2.创建基本结构 3.MyBatisUtils.java和jdbc.properties和mybatis-config.xml与原来的一致4.IdenCard.java5.Person.java6.IdenCardMapper.java7…

使用 uni-app 开发 iOS 应用的操作步骤

哈喽呀&#xff0c;大家好呀&#xff0c;淼淼又来和大家见面啦&#xff0c;上一期和大家一起探讨了使用uniapp开发iOS应用的优势及劣势之后有许多小伙伴想要尝试使用uniapp开发iOS应用&#xff0c;但是却不懂如何使用uniapp开发iOS应用&#xff0c;所以这一期淼淼就来给你们分享…

TCP三次握手,四次挥手

TCP三次握手 TCP协议 &#xff1a; 1。源端口 &#xff1a;当前的进程端口&#xff0c;2字节 2。目的端口&#xff1a;对方的端口 &#xff0c;2字节 3。序号&#xff1a;客户端或者服务器端生成的随机数 4.确认序号&#xff1a;确认上一次发送给数据对方有没有收到 5.标志…

三数之和细节

这道题看着简单&#xff0c;但是有细节要注意&#xff0c;不能有重复的三元组&#xff0c;我们也不能一开始的时候把重复的元素去除&#xff0c;如果全都是0的话&#xff0c;那么就删除的只剩下一个0了&#xff0c;显然答案是[0,0,0] class Solution { public:vector<vecto…

Jetpack Compose简介

文章目录 Jetpack Compose简介概述声明式UI和命令式UIJetpack Compose和Android View对比Compose API设计原则一切皆为函数组合优于继承单一数据源 Jetpack Compose和Android View关系使用ComposesetContent()源码ComposablePreview Jetpack Compose简介 概述 Jetpack Compos…

用龙梦迷你电脑福珑2.0做web服务器

用龙梦迷你电脑福珑2.0上做web服务器是可行的。已将一个网站源码放到该电脑&#xff0c;在局域网里可以访问网站网页。另外通过在同一局域网内的一台windows10电脑上安装花生壳软件&#xff0c;也可以在外网访问该内网服务器网站网页。该电脑的操作系统属于LAMP。在该电脑上安装…

【python】python标准化考试系统[单项选择题 简易版](源码)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

docker挂载数据卷-以nginx为例

目录 一、什么是数据卷 二、数据卷的作用 三、如何挂载数据卷 1、创建nginx容器挂载数据卷 2、查看数据卷 3、查看数据卷详情 4、尝试在宿主机修改数据卷 5、查看容器内对应的数据卷目录 6、 访问nginx查看效果 ​​​​​​​一、什么是数据卷 挂载数据卷本质上就是实…

基于springboot实现公司日常考勤系统项目【项目源码+论文说明】

基于springboot实现公司日常考勤系统演示 摘要 目前社会当中主要特征就是对于信息的传播比较快和信息内容的安全问题&#xff0c;原本进行办公的类型都耗费了很多的资源、传播的速度也是相对较慢、准确性不高等许多的不足。这个系统就是运用计算机软件来完成对于企业当中出勤率…

Unity3D初级实战项目之方块跑酷

目录 初始化项目开发环境初始化项目屏幕自适应 游戏UI界面元素布局开始界面UI角色选择&#xff08;商城&#xff09;界面UI游戏界面UI 地图生成算法之菱形布局Resources资源加载代码生成地图菱形布局 地图生成算法之墙壁边界菱形地图双排布局地图瓷砖颜色美化墙壁边界生成 地图…

git提交错了?别慌,直接删除提交记录

为什么要删除提交历史 前几天产品提了个很扯淡的需求&#xff0c;我在代码了进行了吐槽.... 要命的是我不下心进行了代码提交&#xff1a; 我们的远程仓库大家都能看见的 这要是被其他人发现就惨了&#xff01;当务之急&#xff0c;我必须立刻马上删除这一条提交记录&#xff…

菜鸡学习netty源码(一)——ServerBootStrap启动

1.概述 对于初学者而然,写一个netty本地进行测试的Server端和Client端,我们最先接触到的类就是ServerBootstrap和Bootstrap。这两个类都有一个公共的父类就是AbstractBootstrap. 那既然 ServerBootstrap和Bootstrap都有一个公共的分类,那就证明它们两个肯定有很多公共的职…

EMP.DLL是什么东西?游戏提示EMP.DLL文件缺失怎么解决

emp.dll文件是Windows操作系统中的一种动态链接库文件&#xff0c;它被设计为可以被多个程序共享使用的模块化文件。这种设计旨在提高系统效率&#xff0c;减少内存消耗&#xff0c;并简化软件的维护和更新。DLL文件通常包含了一系列相关的函数和变量&#xff0c;这些函数和变量…

全景剖析阿里云容器网络数据链路(七):Terway DataPath V2(Terway≥1.8.0)

作者&#xff1a;余凯 前言 近几年&#xff0c;企业基础设施云原生化的趋势越来越强烈&#xff0c;从最开始的IaaS化到现在的微服务化&#xff0c;客户的颗粒度精细化和可观测性的需求更加强烈。容器网络为了满足客户更高性能和更高的密度&#xff0c;也一直在高速的发展和演…

qt学习篇---界面按键关联(信号和槽)

目录 1.qt基础 2.做一个界面 创建project UI界面设计 信号和槽 1.控件改名字 2.什么是信号和槽 3.怎么关联信号和槽 自动关联 手动关联 1.qt基础 qt可移植性强&#xff0c;不久会用到MCU。很有意义学习 2.做一个界面 创建project 不要中文路径 选择QWidget .pro文件…

ASP.NET实验室预约系统的设计

摘 要 实验室预约系统的设计主要是基于B/S模型&#xff0c;在Windows系统下&#xff0c;运用ASP.NET平台和SQLServer2000数据库实现实验室预约功能。该设计主要实现了实验室的预约和管理功能。预约功能包括老师对实验室信息、实验项目和实验预约情况的查询以及对实验室的预约…