【BFS专题】— 解决拓扑排序问题

news2024/11/16 18:57:41

拓扑排序介绍:

1、课程表 - 力扣(LeetCode)

思路:

  1. 通过Map<Integer, List<Integer>> 来创建邻接图,数组来表示入度
  2. 然后遍历课程数组,建图
  3. 然后再拓扑排序,bfs
  4. 最后在遍历入度数组,判断有没有环,即是不是入度都为零
  5. 代码:
    class Solution {
        public boolean canFinish(int n, int[][] p) {
            //1、准备工作
            //统计每个顶点的如度
            int[] in = new int[n];
            //构造邻接图表
            Map<Integer, List<Integer>> edges = new HashMap<>();
            //2、建图
            for(int i = 0; i < p.length; i++){
                int a = p[i][0];
                int b = p[i][1];
                if(!edges.containsKey(b)){
                    edges.put(b, new ArrayList<>());
                }
                edges.get(b).add(a);
                //入度加一
                in[a]++;
            }
    
            //3、拓扑排序
            //先把入度为零的点加入到对列中
            Queue<Integer> q = new LinkedList<>();
            for(int i = 0; i < n; i++){
                if(in[i] == 0){
                    q.offer(i);
                }
            }
            //bfs
            while(!q.isEmpty()){
                int t = q.poll();
                for(int a : edges.getOrDefault(t, new ArrayList<>())){
                    in[a]--;
                    if(in[a] == 0){
                        q.offer(a);
                    }
                }
            }
            //4、判断是否有环
            for(int x : in){
                if(x != 0){
                    return false;
                }
            }
            return true;
        }
    }

2、课程表 II - 力扣(LeetCode) 

思路:

  1. 和上一题一样,把最后出队的元素加入到数组中即可
  2. 代码:
    public int[] findOrder(int n, int[][] p) {
            //准备工作
            List<List<Integer>> edges = new ArrayList<>();
            int[] in = new int[n];
            for(int i = 0; i < n; i++){
                edges.add(new ArrayList<>());
            }
            //建图
            for(int i = 0; i < p.length; i++){
                int a = p[i][0];
                int b = p[i][1];
                edges.get(b).add(a);
                in[a]++;
            }
            //拓扑排序
            //入度为0 的点入队
            Queue<Integer> q = new LinkedList<>();
            for(int i = 0; i < n; i++){
                if(in[i] == 0){
                    q.add(i);
                }
            }
            //bfs
            int[] ret = new int[n];
            int index = 0;
            while(!q.isEmpty()){
                int t = q.poll();
                ret[index++] = t;
                for(int a : edges.get(t)){
                    in[a]--;
                    if(in[a] == 0){
                        q.add(a);
                    }
                }
            }
            //判断
            if(index == n){
                return ret;
            }else{
                return new int[0];
            }
        }

3、 火星词典 - 力扣(LeetCode)

思路:

  1. 拓扑排序
    建图:用Map<Character, Set<Character>>
    统计入度:Map<Character, Integer>
  2. 细节问题:当第一组的字符串长度大于第二组的字符串时,不合法
  3. 代码:
    class Solution {
        Map<Character, Set<Character>> edges = new HashMap<>();//邻接表
        Map<Character, Integer> in = new HashMap<>();//统计每个节点的入度
        boolean check;
        public String alienOrder(String[] words) {
            //1、初始化入度的哈希表和建邻接表
            for(String s : words){
                for(int i = 0; i < s.length(); i++){
                    char ch = s.charAt(i);
                    in.put(ch, 0);
                }
            }
            int n = words.length;
            for(int i = 0; i < n; i++){
                for(int j = i + 1; j < n; j++){
                    add(words[i],words[j]);
                    if(check == true){
                        return "";
                    }
                }
            }
            //2、拓扑排序
            Queue<Character> q = new LinkedList<>();
            //将入度为零的节点都入队
            for(char ch : in.keySet()){
                if(in.get(ch) == 0){
                    q.offer(ch);
                }
            }
            StringBuffer ret = new StringBuffer();
            //遍历队列
            while(!q.isEmpty()){
                char t = q.poll();
                ret.append(t);
                if(!edges.containsKey(t)){
                    continue;
                }
                for(char ch : edges.get(t)){
                    in.put(ch, in.get(ch) - 1);
                    if(in.get(ch) == 0){
                        q.add(ch);
                    }
                }
            }
            //3、判断,是否入度都是为零
            for(char ch : in.keySet()){
                if(in.get(ch) != 0){
                    return "";
                }
            }
            return ret.toString();
        }
        //处理字符串
        public void add(String s1, String s2){
            int n = Math.min(s1.length(), s2.length());
            int i = 0;
            for( ; i < n; i++){
                char c1 = s1.charAt(i);
                char c2 = s2.charAt(i);
                if(c1 != c2){
                    if(!edges.containsKey(c1)){
                        edges.put(c1, new HashSet<>());
                    }
                    if(!edges.get(c1).contains(c2)){
                        edges.get(c1).add(c2);
                        in.put(c2, in.get(c2)+1);
                    }
                    break;
                }
            }
            if(i == s2.length() && i < s1.length()){
                check = true;
            }
        }
    }

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

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

相关文章

ADB ROOT开启流程

开启adb root 选项后&#xff0c;执行如下代码&#xff1a; packages/apps/Settings/src/com/android/settings/development/AdbRootPreferenceController.java mADBRootService new ADBRootService(); Override public boolean onPreferenceChange(Preference preference…

(十五)、把自己的镜像推送到 DockerHub

文章目录 1、登录Docker Hub2、标记&#xff08;Tag&#xff09;镜像3、推送&#xff08;Push&#xff09;镜像4、查看镜像5、下载镜像6、设置镜像为公开或者私有 1、登录Docker Hub 需要科学上网 https://hub.docker.com/ 如果没有账户&#xff0c;需要先注册一个。登录命令如…

基于用户增长的动销方案实践!

在竞争激烈的市场环境下&#xff0c;实现用户增长和推动产品动销至关重要。 首先&#xff0c;明确市场定位与目标用户群体&#xff0c;通过市场调研深入了解用户需求和痛点&#xff0c;进行精准营销。同时&#xff0c;不断优化用户体验&#xff0c;提升产品质量和性能&#xff…

服装企业必备增长利器:高效商品管理系统

在时尚界的快车道上&#xff0c;服装企业如同驾驶着赛车&#xff0c;在瞬息万变的市场中疾驰。为了在这场激烈的竞赛中保持领先&#xff0c;服装企业迫切需要一把能够助其精准操作、高效运转的钥匙——商品管理系统。这不仅仅是一个软件工具&#xff0c;更是企业应对市场挑战、…

碰撞检测 | 图解线段几何与线段相交检测原理(附ROS C++可视化)

目录 0 专栏介绍1 线段与线段相交检测2 线段与圆相交检测3 线段与矩形相交检测4 算法仿真与可视化4.1 核心算法4.2 仿真实验 0 专栏介绍 &#x1f525;课设、毕设、创新竞赛必备&#xff01;&#x1f525;本专栏涉及更高阶的运动规划算法轨迹优化实战&#xff0c;包括&#xf…

[Java]maven从入门到进阶

介绍 apache旗下的开源项目,用于管理和构建java项目的工具 官网: Welcome to The Apache Software Foundation! 1.依赖管理 通过简单的配置, 就可以方便的管理项目依赖的资源(jar包), 避免版本冲突问题 优势: 基于项目对象模型(POM),通过一小段描述信息来管理项目的构建 2…

第六天旅游线路规划

第五天&#xff1a;从贾登峪返回乌鲁木齐&#xff1b; 第六天&#xff1a;从乌鲁木齐到天山天池&#xff0c;晚上回乌鲁木齐住宿。 第六天从乌鲁木齐到天山天池景区入口的的规划结果见下图&#xff1a; 1、行程安排 根据上面的耗时情况&#xff0c;规划一天的行程安排如下&a…

OFDM简介

OFDM(Orthogonal Frequency Division Multiplexing)全称为正交频分复用&#xff0c;在无线通信中被广泛应用。本文结合下图对OFDM的基本原理进行说明。 图1. OFDM信号生成流程示意图 上图为OFDM信号生成、传输和接收的整体流程图。结合该流程图对其中每一个模块进行详细说明。 …

Logstash 安装与部署(无坑版)

下载 版本对照关系&#xff1a;ElasticSearch 7.9.2 和 Logstash 7.9.2 &#xff1b; 官方下载地址 选择ElasticSearch版本一致的Logstash版本 https://www.elastic.co/cn/downloads/logstash 下载链接&#xff1a;https://artifacts.elastic.co/downloads/logstash/logst…

一、XML与Tomcat

文章目录 1. XML简介1.1 什么是XML1.2 XML的作用 2. XML语法2.1 文档声明2.2 xml 注释2.3 元素&#xff08;标签&#xff09;2.4 xml 属性2.5 语法规则2.5.1 所有XML元素都须有关闭标签&#xff08;也就是闭合&#xff09;2.5.2 XML 标签对大小写敏感2.5.3 XML 必须正确地嵌套2…

# windows 运行框输入mrt提示错误:Windows 找不到文件‘mrt‘。请确定文件名是否正确后,再试一次

windows 运行框输入mrt提示错误&#xff1a;Windows 找不到文件’mrt’。请确定文件名是否正确后&#xff0c;再试一次 一、错误描述&#xff1a; 当您在 windows 运行框中输入mrt并收到错误提示“Windows 找不到文件’mrt’。请确定文件名是否正确后,再试”时&#xff0c;这…

【无人机设计与控制】四旋翼无人机轨迹跟踪及避障Matlab代码

摘要 本文主要研究了四旋翼无人机在复杂环境中的轨迹跟踪与避障控制策略。通过Matlab/Simulink对四旋翼无人机进行了建模与仿真。系统集成了避障算法&#xff0c;使得无人机在执行任务时能够有效避开障碍物&#xff0c;保证飞行的安全性与稳定性。 理论 无人机飞行控制通常涉…

着色器 简介

着色器&#xff08;Shader&#xff09;是运行在 GPU 上的小程序。这些小程序为图形渲染管线的某个特定部分而运行。从基本意义上来说&#xff0c;着色器只是一种把输入转化为输出的程序。着色器也是一种非常独立的程序&#xff0c;因为它们之间不能相互通信&#xff1b;它们之间…

【JavaSE】--数组的定义与使用

文章目录 1. 数组的基本概念1.1 什么是数组1.2 数组的创建及初始化1.2.1 数组的创建1.2.2 数组的初始化 1.3 数组的使用1.3.1 数组中元素访问1.3.2 遍历数组 2. 数组是引用类型2.1 初识JVM的内存分布2.2 基本类型变量与引用类型变量的区别2.3 再谈引用变量2.4 认识null 3. 数组…

es的封装

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、类和接口介绍0.封装思想1.es的操作分类 二、创建索引1.成员变量2.构造函数2.添加字段3.发送请求4.创建索引总体代码 三.插入数据四.删除数据五.查询数据 前…

公共建筑能耗监测系统解决方案

jianzhunenghao 建筑节能监测系统公共建筑能耗监测系统建筑能耗监测系统节能监测系统能耗监测建筑能耗监测能耗分析能耗管理能耗预测能耗监控能耗监测平台建筑能耗 介绍 能耗监控系统是为耗电量、耗水量、耗气量&#xff08;天然气量或者煤气量&#xff09;、集中供热耗热量…

STHS34PF80高灵敏度红外感应器(2)----InfraredPD存在感应检测

STHS34PF80人体存在传感器.2--InfraredPD存在感应检测 概述视频教学样品申请完整代码下载硬件准备开启CRC串口设置开启X-CUBE-MEMS1InfraredPD文件InfraredPD算法库注意事项对应DEMOMX_MEMS_InitMX_MEMS_Processt_obj_comp&#xff08;补偿后的物体温度&#xff09;t_obj_chang…

清理C盘缓存,电脑缓存清理怎么一键删除,操作简单的教程

清理C盘缓存是维护电脑性能、释放磁盘空间的重要步骤。以下是一个详细且操作简单的教程&#xff0c;旨在帮助用户通过一键或几步操作完成C盘缓存的清理。 1.使用Windows系统自带工具 磁盘清理 1.打开磁盘清理工具&#xff1a; -按下“WinE”打开文件资源管理器…

数据结构与算法——Java实现 5.链表

目录 一、定义 链表的分类 二、性能 随机访问 插入或删除 三、单向链表 链表内部节点类 ① 增加&#xff08;插入&#xff09; 1.头插法 2.寻找最后一个节点位置 3.尾插法 4.根据索引位置插入 ② 删除 1.删除首个结点 2.获取链表的指定索引节点 3.删除链表指定索引元素节点 4.删…

【Java】【力扣】83.删除排序链表中的重复元素

题目 给定一个已排序的链表的头 head &#xff0c; 删除所有重复的元素&#xff0c;使每个元素只出现一次 。返回 已排序的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,1,2] 输出&#xff1a;[1,2]示例 2&#xff1a; 输入&#xff1a;head [1,1,2,3,3] 输出&#…