拓扑排序专题篇

news2024/9/21 14:57:23

目录

前言

课程表

课程表II

课程表IV

火星词典


前言

拓扑排序是指对一个有向无环图的节点进行排序之后得到的序列,如果存在一条从节点A指向节点B的边,那么在拓扑排序的序列中节点A出现在节点B的前面。一个有向无环图可以有一个或多个拓扑排序序列,但无向图或有向图都不存在拓扑排序。

一种常用的拓扑排序算法是每次从有向无环图中取出一个入度为0的节点添加到拓扑排序序列之中,然后删除该节点及所有以他为起点的边。重复这个步骤,直到图为空或图中不存在入度为0的节点。如果最终图为空,那么图是有向无环图,此时就找到了该图的一个拓扑排序序列。如果最终图不为空并且已经不存在入度为0的节点,那么该图一定有环。

课程表

题目

思路

首先先建图,可以采用邻接矩阵或者邻接表建图,解题时采用邻接表来建图,并统计每个节点的入度,然后扫描所有节点的入度,将入度尾0的节点加入到队列中,取出队头元素,将该节点加入数组中,并将以该节点为起始点的边的终点的入度-1,如果有节点的入度为0,就将该节点加入队列中,最后,如果数组的大小和课程数目不相等,说明存在环,不能修完课程;否则能修完课程。

代码

class Solution {
public:
    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
        vector<int> in(numCourses);
        vector<vector<int>> vv(numCourses);
        vector<int> v;
        for(auto it:prerequisites){
            vv[it[1]].push_back(it[0]);
            in[it[0]]++;
        }
        queue<int> q;
        for(int i=0;i<numCourses;i++)
            if(in[i]==0) q.push(i);
        while(!q.empty()){
            int ret=q.front();
            q.pop();
            v.push_back(ret);
            for(int x:vv[ret])
                if(--in[x]==0)
                    q.push(x);
        }
        if(v.size()==numCourses) return true;
        else return false;
    }
};
课程表II

题目

思路

这道题和上一道题其实是一样的,只不过是问题不同而已,解决方法还是首先先建图,可以采用邻接矩阵或者邻接表建图,解题时采用邻接表来建图,并统计每个节点的入度,然后扫描所有节点的入度,将入度尾0的节点加入到队列中,取出队头元素,将该节点加入数组中,并将以该节点为起始点的边的终点的入度-1,如果有节点的入度为0,就将该节点加入队列中,最后,如果数组的大小和课程数目不相等,说明存在环,不能修完课程;否则能修完课程。

代码

class Solution {
public:
    vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
        unordered_map<int,vector<int>> hash;
        vector<int> in(numCourses);
        vector<int> ret;
        for(auto it:prerequisites){
            hash[it[1]].push_back(it[0]);
            in[it[0]]++;
        }
        queue<int> q;
        for(int i=0;i<numCourses;i++)
            if(in[i]==0) q.push(i);
        while(!q.empty()){
            int top=q.front();q.pop();
            ret.push_back(top);
            for(int x:hash[top])
                if(--in[x]==0)
                    q.push(x);
        }
        if(ret.size()==numCourses) return ret;
        else return {};
    }
};



// class Solution {
// public:
//     vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
//         vector<int> in(numCourses);
//         vector<vector<int>> vv(numCourses);
//         vector<int> ret;
//         for(auto it:prerequisites){
//             vv[it[1]].push_back(it[0]);
//             in[it[0]]++;
//         }
//         queue<int> q;
//         for(int i=0;i<numCourses;i++)
//             if(in[i]==0) q.push(i);
//         while(!q.empty()){
//             int top=q.front();q.pop();
//             ret.push_back(top);
//             for(int x:vv[top])
//                 if(--in[x]==0)
//                     q.push(x);
//         }
//         if(ret.size()==numCourses) return ret;
//         else return {};
//     }
// };
课程表IV

题目

思路

虽然这道题和前两道题看起来是一样的,但是这道题比前两道题要难一些,因为对于每一遍扫描到的入度为0的节点,这些节点之间是没有先决条件关系的,如果还用之前的解法,会把每一遍扫描到的入度为0的节点赋予先决条件,因此我们需要使用别的方法。

下面,先使用邻接表建图,然后扫描每个节点,进行深度优先遍历,如果该节点没有被遍历过,则遍历以该节点为起始点的所有边的终点,依旧是判断该节点有没有被遍历过,如果没有被遍历过,则遍历以该节点为起始点的所有边的终点,然后将邻接矩阵中的起始点到终点的值置为true,然后遍历所有终点,看是否存在以终点为起始点的点,然后将邻接矩阵中起始点到终点的终点的值置为isPre[pos][i]=isPre[pos][i]|isPre[x][i]。

代码

class Solution {
public:
    vector<bool> checkIfPrerequisite(int numCourses, vector<vector<int>>& prerequisites, vector<vector<int>>& queries) {
        vector<vector<int>> edges(numCourses);
        vector<bool> vis(numCourses,false);
        vector<vector<bool>> isPre(numCourses,vector<bool>(numCourses,false));
        for(auto& p:prerequisites)
            edges[p[0]].push_back(p[1]);
        for(int i=0;i<numCourses;i++)
            dfs(edges,isPre,vis,i);
        vector<bool> res;
        for(auto& query:queries)
            res.push_back(isPre[query[0]][query[1]]);
        return res;
    }

    void dfs(vector<vector<int>>& edges,vector<vector<bool>>& isPre,vector<bool>& vis,int pos){
        if(vis[pos]) return;
        vis[pos]=true;
        for(int x:edges[pos]){
            dfs(edges,isPre,vis,x);
            isPre[pos][x]=true;
            for(int i=0;i<isPre.size();i++)
                isPre[pos][i]=isPre[pos][i]|isPre[x][i];
        }
    }
};





//chatGpt的答案
// class Solution {
// public:
//     vector<bool> checkIfPrerequisite(int numCourses, vector<vector<int>>& prerequisites, vector<vector<int>>& queries) {
//         vector<vector<int>> adjacencyList(numCourses);
//         vector<vector<int>> successors(numCourses);
//         vector<bool> visited(numCourses, false);
//         unordered_map<int, int> topoOrderIndex;  // Store the index of each course in topological order
//         queue<int> q;
        
//         // Construct adjacency list and initialize in-degree counts
//         vector<int> inDegree(numCourses, 0);
//         for (const auto& prerequisite : prerequisites) {
//             int course = prerequisite[0];
//             int prerequisiteCourse = prerequisite[1];
//             adjacencyList[course].push_back(prerequisiteCourse);
//             inDegree[prerequisiteCourse]++;
//         }
        
//         // Perform topological sort and record the order
//         for (int i = 0; i < numCourses; ++i) {
//             if (inDegree[i] == 0) {
//                 q.push(i);
//             }
//         }
//         int topoIndex = 0;
//         while (!q.empty()) {
//             int current = q.front();
//             q.pop();
//             topoOrderIndex[current] = topoIndex++;
//             for (int successor : adjacencyList[current]) {
//                 if (--inDegree[successor] == 0) {
//                     q.push(successor);
//                 }
//                 successors[current].push_back(successor);
//             }
//         }
        
//         // Handle queries
//         vector<bool> results;
//         for (const auto& query : queries) {
//             int courseA = query[0];
//             int courseB = query[1];
//             bool isPrerequisite = dfs(courseA, courseB, successors, visited, topoOrderIndex);
//             results.push_back(isPrerequisite);
//             fill(visited.begin(), visited.end(), false); // Reset visited for the next query
//         }
        
//         return results;
//     }
    
// private:
//     bool dfs(int courseA, int courseB, const vector<vector<int>>& successors, vector<bool>& visited, const unordered_map<int, int>& topoOrderIndex) {
//         if (courseA == courseB) {
//             return true;
//         }
//         visited[courseA] = true;
//         for (int successor : successors[courseA]) {
//             if (!visited[successor] && (topoOrderIndex.at(courseA) < topoOrderIndex.at(successor))) {
//                 if (successor == courseB || dfs(successor, courseB, successors, visited, topoOrderIndex)) {
//                     return true;
//                 }
//             }
//         }
//         return false;
//     }
// };
火星词典

题目

思路

这道题的题目首先得看懂,然后解析所有字符串,两个字符串满足前一个字符串的前n个字符和后一个字符串的前n个字符相同,第一次出现不同字符时,前一个字符串的第n+1个字符的序列小于后一个字符串的第n+1个字符的序列,如果第一个字符串的长度大于第二个字符串的长度,且第一个字符串的长度为第二个字符串长度的字符和第二个字符串相等,这样是不符合题意的,直接返回空串;否则就建立邻接表,并统计所有节点的入度信息,将入度为0的节点的值加入队列,然后取出队头元素,将该节点加入字符串末尾,并将以该节点为起始点的边的终点的入度-1,如果有节点的入度为0,就将该节点加入队列中,执行将该节点加入字符串末尾,并将以该节点为起始点的边的终点的入度-1,如果有节点的入度为0,就将该节点加入队列中。

最后扫描数组,如果存在某个节点的入度不为0,说明存在环,不能排序,返回空串;否则返回结果字符串。

代码

class Solution {
    unordered_map<char,unordered_set<char>> edges;
    unordered_map<char,int> in;
    bool flag;
public:
    string alienOrder(vector<string>& words) {
        for(string s:words)
            for(char ch:s)
                in[ch]=0;
        int n=words.size();
        for(int i=0;i<n-1;i++)
            for(int j=i+1;j<n;j++){
                helper(words[i],words[j]);
                if(flag) return "";
            }
        queue<char> q;
        string s;
        for(auto& [a,b]:in){
            if(b==0) q.push(a);
        }
        while(!q.empty()){
            int ch=q.front();q.pop();
            s+=ch;
            for(char c:edges[ch])
                if(--in[c]==0)
                    q.push(c);
        }
        for(auto& [a,b]:in)
            if(b!=0) return "";
        return s;
    }

    void helper(string& s1,string& s2){
        int n=min(s1.size(),s2.size());
        int i=0;
        for(;i<n;i++)
            if(s1[i]!=s2[i]){
                char a=s1[i],b=s2[i];
                if(!edges.count(a) || !edges[a].count(b)){
                    edges[a].insert(b);
                    in[b]++;
                }
                break;
            }
        if(i==s2.size() && i<s1.size())
            flag=true;
    }
};

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

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

相关文章

QT Layout布局,隐藏其中的某些部件后,不影响原来的布局

最近在工作时&#xff0c;被要求&#xff0c;需要将布局中的某些部件隐藏后&#xff0c;但不能影响原来的布局。 现在记录解决方案&#xff01; 一、水平布局&#xff08;垂直布局一样&#xff09; ui中的布局 效果&#xff1a; 按钮可以任意隐藏&#xff0c;都不影响其中布…

基于双PI矢量控制结构和SVPWM的风力发电系统Simulink建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 PMSM数学模型 4.2 双PI控制结构 4.3 SVPWM 5.完整工程文件 1.课题概述 风力发电系统的核心是风力发电机&#xff0c;常见的有永磁同步发电机和感应发电机&#xff08;IG&#xff09;。这些发电机通…

XML_Tomcat_HTTP

第四章 XML_Tomcat10_HTTP 一 XML XML是EXtensible Markup Language的缩写&#xff0c;翻译过来就是可扩展标记语言。所以很明显&#xff0c;XML和HTML一样都是标记语言&#xff0c;也就是说它们的基本语法都是标签。 可扩展 三个字表面上的意思是XML允许自定义格式。但这不代…

用Python打造互动式中秋节庆祝小程序

中秋节&#xff0c;这个充满传统韵味的节日&#xff0c;不仅是家人团聚的时刻&#xff0c;也是程序员展示创意的好机会。本文将引导您使用Python创建一个互动式中秋节庆祝小程序&#xff0c;它不仅能够展示节日祝福&#xff0c;还能通过一些简单的特效增加节日气氛。 文章目录 …

python数据分析 pandas库-数据的读取和保存

python数据分析 pandas库-数据读取和保存 一、数据文件 在数据分析中&#xff0c;数据的读取是非常重要的一步。Pandas 提供了丰富的接口来读取各种格式的数据文件&#xff0c;例如 CSV、Excel、JSON、SQL 数据库等。接下来我们将详细说明如何使用 Pandas 读取不同格式的数据…

【人工智能学习笔记】6_自然语言处理基础

自然语言处理基本介绍 自然语言:指人类使用的在社会生活中自然形成的语言; 自然语言处理:指计算机识别、理解、计算分析、生成自然语言的过程。 包含自然语言理解和自然语言生成两部分的两大研究方向。 自然语言理解:所有支持机器理解文本内容的方法模型或任务的总称,是推…

代理IP批理检测工具,支持socks5,socks4,http和https代理批量检测是否可用

代理IP批理检测工具,支持socks5,socks4,http和https代理批量检测是否可用 工具使用c编写&#xff1a; 支持ipv4及ipv6代理服务器。 支持http https socks4及socks5代理的批量检测。 支持所有windows版本运行&#xff01; 导入方式支持手工选择文件及拖放文件。 导入格式支持三…

常用游戏运行库下载

包含以下资源&#xff1a; DirectX Repair.exe DirectX Repair(Enhanced Edition). vcredist C2013 x64.exe 微软常用运行库合集 下载链接

Puppet 部署应用(Puppet deployment application)

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:Linux运维老纪的首页…

逻辑漏洞-其二(登录验证码安全)

2.登录验证码安全 验证码漏洞检测流程 2.1 图形验证码 无效验证 2.1.1 验证码可爆破 验证码可爆破&#xff0c;即验证码过于简单&#xff0c;例如验证码中字符数量过少&#xff0c;比如只有四位组成&#xff0c;且只包含 0-9 的数字还没有干扰点 &#xff0c;亦或者 验证码可以…

Python---爬虫

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 Python爬虫是一种通过自动化程序爬取互联网上的信息的技术。爬虫可以自动访问网页并提取所需的数据&#xff0c;比如网站的文本、图片、视频等。Python是一种简单易学的编程语言&#xff…

建筑裂缝检测图像ai模型训练数据集

共52w例图像的建筑裂缝检测图像ai模型训练数据集 20 地上设施&#xff08;公路桥梁、铁路桥梁、水坝&#xff08;墙&#xff09;、挡土墙&#xff09;和地下 SOC 设施&#xff08;公路/铁路隧道、地铁、水隧道&#xff09;&#xff1b;韩国40 个市、县、区 SOC 设施的数据&…

读构建可扩展分布式系统:方法与实践05分布式缓存

1. 分布式缓存 1.1. 缓存存在于应用程序的许多地方 1.1.1. 行应用程序的CPU具有高速多级硬件缓存&#xff0c;可以减少相对较慢的主内存访问 1.1.2. 数据库引擎可以利用主内存来缓存数据存储的内容&#xff0c;这样在许多情况下查询就可以不用访问速度相对较慢的磁盘 1.2. …

给树莓派添加 SSD1306 OLED 小屏幕

树莓派被作为一个小服务器使用的时候&#xff0c;通常都不需要接一台专用显示器&#xff0c;而是通过 ssh 远程登录。当环境中有多个设备使用远程登录的时候&#xff0c;就容易不记得相应设备的 IP 地址等信息&#xff1b;有时候只是需要了解设备的一些信息&#xff0c;例如 CP…

【GPU版】Windows下PyTorch入门深度学习环境安装与配置

如果电脑有NVIDIA GPU显卡&#xff0c;看【GPU版本】&#xff1b;否则&#xff0c;看【CPU版本】 聊聊PyTorch和Tensorflow 它们都是python的库/包 pip3是给python3使用的&#xff0c;由于现在用的python基本上都是3以上版本&#xff0c;所以pip和pip3没有区别 聊聊Anacond…

✔3290. 最高乘法得分

代码实现&#xff1a; 动态规划 /*从 b 中选一个长为 4 的子序列定义 dfs(i,j) 表示 从 b[0] 到 b[i] 中选出 j1 个数&#xff0c;去和 a[0] 到 a[j] 算一个点积的最大值考虑 b[i] 选或不选不选 dfs(i-1,j)选 dfs(i-1,j-1) a[j] * b[i]dfs(i,j) max(dfs(i-1),j), dfs(i-1,j-1…

FreeRTOS实战指南 — 2 移植 FreeRTOS 到 STM32F429

目录 1 准备裸机工程文件 2 创建FreeRTOS文件夹结构 3 修改Keil工程文件 3.1 添加工程文件 3.2 指定 FreeRTOS 头文件的路径 4 移植FreeRTOSConfig.h配置文件 4.1 移植FreeRTOSConfig.h 4.2 详解FreeRTOSConfig.h 4.3 修改FreeRTOSConfig.h 5 修改main.c 1 准备裸机工…

Java | Leetcode Java题解之第409题最长回文串

题目&#xff1a; 题解&#xff1a; class Solution {public int longestPalindrome(String s) {int[] count new int[128];int length s.length();for (int i 0; i < length; i) {char c s.charAt(i);count[c];}int ans 0;for (int v: count) {ans v / 2 * 2;if (v …

开源 AI 智能名片小程序:开启内容营销新境界

摘要&#xff1a;本文深入探讨了在当今数字化时代&#xff0c;内容营销的重要性以及如何实现让用户主动找你的最佳效果。通过引入开源 AI 智能名片小程序这一创新工具&#xff0c;阐述了其在明确目标用户群体、迎合用户需求痛点和打造风格特色方面的独特优势&#xff0c;为企业…

VMware ESXi 7.0U3q macOS Unlocker 集成驱动版更新 OEM BIOS 2.7 支持 Windows Server 2025

VMware ESXi 7.0U3q macOS Unlocker 集成驱动版更新 OEM BIOS 2.7 支持 Windows Server 2025 VMware ESXi 7.0U3q macOS Unlocker & OEM BIOS 2.7 集成网卡驱动和 NVMe 驱动 (集成驱动版) ESXi 7.0U3 标准版集成 Intel 网卡、Realtek USB 网卡 和 NVMe 驱动 请访问原文链…