【优选算法专栏】专题十六:BFS解决最短路问题(二)

本专栏内容为:算法学习专栏,分为优选算法专栏,贪心算法专栏,动态规划专栏以及递归,搜索与回溯算法专栏四部分。 通过本专栏的深入学习,你可以了解并掌握算法。

💓博主csdn个人主页:小小unicorn
⏩专栏分类:算法从入门到精通
🚚代码仓库:小小unicorn的代码仓库🚚
🌹🌹🌹关注我带你学习编程知识

专题十六

  • 最小基因变化
    • 算法原理
  • 单词接龙
    • 算法原理:
  • 为高尔夫比赛砍树
    • 算法原理:

最小基因变化

题目来源:Leetcode433.最小基因变化

基因序列可以表示为一条由 8 个字符组成的字符串,其中每个字符都是 ‘A’、‘C’、‘G’ 和 ‘T’ 之一。

假设我们需要调查从基因序列 start 变为 end 所发生的基因变化。一次基因变化就意味着这个基因序列中的一个字符发生了变化。

例如,“AACCGGTT” --> “AACCGGTA” 就是一次基因变化。
另有一个基因库 bank 记录了所有有效的基因变化,只有基因库中的基因才是有效的基因序列。(变化后的基因必须位于基因库 bank 中)

给你两个基因序列 start 和 end ,以及一个基因库 bank ,请你找出并返回能够使 start 变化为 end 所需的最少变化次数。如果无法完成此基因变化,返回 -1 。

注意:起始基因序列 start 默认是有效的,但是它并不一定会出现在基因库中。
在这里插入图片描述

算法原理

本题目首先可以进行转化:

->转化为图论问题中的边权为1的最短路问题。
在这里插入图片描述

根据基因变换只能变换一个,我们把每一个基因抽象成一个点,那么这个问题就可以转化为:已知起点位置和终点位置,从起点位置到终止位置的最短路径,由于每次只能变换一个字母,所以边权都为1。

分析到这,解题思路就是用BFS。

但是在写代码前,还需注意一下细节:
在这里插入图片描述

  1. 为防止有的遍历重复,我们需要用一个数组来进行标记,但是普通数组显然不能满足需求,因为存的是字符串,所以我们应用哈希表进行储存。

  2. 如何枚举出所有的情况呢?
    答案很简单,我们暴力枚举一下字符串即可。

  3. 枚举出的所以情况,都需要加入到队列里么?
    答案是不需要,因为本身存在一个基因库,在枚举字符串中,在基因库中我们才进入队列。

  4. 如何快速判断在基因库中存在?
    普通做法就是直接遍历整个基因库,但是这样还是显得太麻烦,我们可以先预处理一下,直接将基因库丢在哈希中,在哈希表中进行查找,方便快速加快效率。

代码实现:

class Solution 
{
public:
    int minMutation(string startGene, string endGene, vector<string>& bank) 
    {
        //用来标记是否是已经搜索过的状态
        unordered_set<string> vis;
        unordered_set<string> hash(bank.begin(),bank.end());//存储基因库中里面的字符串
        string change="ACGT";

        //处理边界情况
        if(startGene==endGene) return 0;

        int ret=0;
        queue<string> q;
        q.push(startGene);
        vis.insert(startGene);
        while(q.size())
        {
            ret++;
            int sz=q.size();
            while(sz--)
            {
                string t=q.front();
                q.pop();
                for(int i=0;i<8;i++)
                {
                    //细节问题
                    string tmp=t;
                    for(int j=0;j<4;j++)
                    {
                        tmp[i]=change[j];
                        if(hash.count(tmp)&&!vis.count(tmp))
                        {
                            if(tmp==endGene)
                            return ret;
                            q.push(tmp);
                            vis.insert(tmp);
                        }
                    }
                }
            }
        }
        return -1;
    }
};

单词接龙

题目来源:108.单词接龙

在字典(单词列表) wordList 中,从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列:

序列中第一个单词是 beginWord 。
序列中最后一个单词是 endWord 。
每次转换只能改变一个字母。
转换过程中的中间单词必须是字典 wordList 中的单词。
给定两个长度相同但内容不同的单词 beginWord 和 endWord 和一个字典 wordList ,找到从 beginWord 到 endWord 的 最短转换序列 中的 单词数目 。如果不存在这样的转换序列,返回 0。

在这里插入图片描述

算法原理:

分析一遍,其实本题跟最小基因库基本是一样的,只是本题的问法不一样:
本题问的是个数,所以我们要再返回层数的基础上加1.
在这里插入图片描述
代码实现:

class Solution 
{
public:
    int ladderLength(string beginWord, string endWord, vector<string>& wordList) 
    {
        //存储单词列表
        unordered_set<string> hash(wordList.begin(),wordList.end());
        unordered_set<string> vis;//标记已经搜索过的单词

        //判断边界情况
        if(!hash.count(endWord)) return 0;

        queue<string> q;
        q.push(beginWord);
        vis.insert(beginWord);

        //因为返回的是个数,所以初始化可以初始化为1
        int ret=1;
        while(q.size())
        {
            ret++;
            int sz=q.size();
            while(sz--)
            {
                string t=q.front();
                q.pop();
                for(int i=0;i<t.size();i++)
                {
                    string tmp=t;
                    for(char ch='a';ch<='z';ch++)
                    {
                        tmp[i]=ch;
                        if(!vis.count(tmp)&&hash.count(tmp))
                        {
                            if(tmp==endWord) return ret;
                            q.push(tmp);
                            vis.insert(tmp);
                        }
                    }
                }
            }
        }
        return 0;
    }
};

为高尔夫比赛砍树

题目来源:Leetcode675.为高尔夫比赛砍树

你被请来给一个要举办高尔夫比赛的树林砍树。树林由一个 m x n 的矩阵表示, 在这个矩阵中:

0 表示障碍,无法触碰
1 表示地面,可以行走
比 1 大的数 表示有树的单元格,可以行走,数值表示树的高度
每一步,你都可以向上、下、左、右四个方向之一移动一个单位,如果你站的地方有一棵树,那么你可以决定是否要砍倒它。

你需要按照树的高度从低向高砍掉所有的树,每砍过一颗树,该单元格的值变为 1(即变为地面)。

你将从 (0, 0) 点开始工作,返回你砍完所有树需要走的最小步数。 如果你无法砍完所有的树,返回 -1 。

可以保证的是,没有两棵树的高度是相同的,并且你至少需要砍倒一棵树。
在这里插入图片描述

算法原理:

本题首先也可以转化:
可以看这个例子:
在这里插入图片描述

根据砍树由低到高,我们可以把砍树的顺序弄出来:
在这里插入图片描述
然后我们让每一段的路径都最小,那么总和肯定也就最小。
那么这个问题就可以转化为我们之前做过的迷宫问题。
而本题是若干个迷宫问题。

还记的什么是迷宫问题吗?
迷宫问题从起始点位置到边界情况下的最短路径,此题是前一个位置到后一个位置的最短路径。

问题解决到这,那么我们又怎么知道砍树顺序呢?
这时就需要用到我们的容器,我们用一个二维数组存储,可以是哈希可以是vector只要能将里面进行排序,那么我们就可以拿来用。

代码解决:

class Solution 
{
    int dx[4]={0,0,1,-1};
    int dy[4]={1,-1,0,0};
    
public:
    int cutOffTree(vector<vector<int>>& f) 
    {
       
        //
        int m = f.size(), n= f[0].size();
        //1.准备工作,找出砍树的顺序
        vector<pair<int,int>> tree;
        for(int i=0;i<m;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(f[i][j]>1)
                    tree.push_back({i,j});
            }
        }
        //排序
        sort(tree.begin(),tree.end(),[&](const pair<int,int>&p1,const pair<int,int>&p2)
        {
            return f[p1.first][p1.second]<f[p2.first][p2.second];
        });
        //2.按照顺序砍树
        int bx=0,by=0;
        int ret=0;
        for(auto& [a,b]:tree)
        {
            int step=bfs(f,bx,by,a,b);
            if(step==-1)
            return -1;
            ret+=step;
            bx=a,by=b;
        }
        return ret;
    }

     //3.bfs
    bool vis[51][51];
    int bfs(vector<vector<int>>& f,int bx,int by,int ex,int ey)
    {
            int m = f.size(), n= f[0].size();
            if(bx==ex&&by==ey) return 0;
            queue<pair<int,int>> q;
            //清空之前数据
            memset(vis,0,sizeof vis);
            q.push({bx,by});
            vis[bx][by]=true;

            int step=0;
            while(q.size())
            {
               
                step++;
                int sz=q.size();
                while(sz--)
                {
                    auto [a,b]=q.front();
                    q.pop();
                    for(int i=0;i<4;i++)
                    {
                        int x=a+dx[i],y=b+dy[i];
                        if(x>=0 && x < m  &&y>=0 && y<n&&f[x][y]&&!vis[x][y])
                        {
                            if(x==ex&&y==ey)
                            return step;
                            q.push({x,y});
                            vis[x][y]=true;
                            
                        }
                    }
                }
                
            }
        return -1;
    }
    
};

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

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

相关文章

主从复制、数据持久化 、Redis主从集群、哨兵机制 、Redis分片集群

数据持久化 Redis、主从集群、哨兵机制 Redis分片集群 1、单点 redis 的问题2、主从复制2.1 命令传播 3、Redis的持久化3.1 AOF3.2 RDB&#xff08;默认方式&#xff09;RDB 方式&#xff1a;执行快照时&#xff0c;数据能被修改吗&#xff1f;RDB 方式总结 3.3 RDB 和 AOF 组合…

ORAN C平面 Section Extension 22

ORAN C平面Section扩展22用于ACK/NACK请求。除section type 7外&#xff0c;section扩展22可以用于从O-DU发送到O-RU的所有section type和section扩展。 对于一个section描述&#xff0c;O-DU可以使用section扩展22要求O-RU使用section type 8 C平面消息进行ACK/NACK反馈。关于…

ctfshow web入门 web29-web38

web29 把flag和i屏蔽了 system函数也行但是通常会屏蔽所以我直接用passthru 看看有啥 cat的话要查看源代码 web30 没有意外把这个system屏蔽了没事我不用哈哈哈 ?cpassthru("cat f*"); 然后查看源代码 web31 把空格屏蔽了 某位大佬的题解看到的 %09或者/**/绕过…

代码随想录第34天| 1005.K次取反后最大化的数组和 134. 加油站 135. 分发糖果

1005.K次取反后最大化的数组和 1005. K 次取反后最大化的数组和 - 力扣&#xff08;LeetCode&#xff09; 代码随想录 (programmercarl.com) 贪心算法&#xff0c;这不就是常识&#xff1f;还能叫贪心&#xff1f;LeetCode&#xff1a;1005.K次取反后最大化的数组和_哔哩哔…

思维的类比

Learn More, Study Less 中提出了整体学习法&#xff08;Holistic learning&#xff09;&#xff0c;其基本思想是&#xff1a;你不可能孤立地学会一个概念&#xff0c;而只能将其融入已有的概念体系中&#xff0c;从不同角度对其进行刻画来弄懂其内涵和外延并且书中使用三个类…

力扣2- 两数相加

给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外&#xff0c;这两个数都不会以 0 …

ubuntu安装

一、安装虚拟机 https://www.vmware.com/products/workstation-pro/workstation-pro-evaluation.html 下载后运行安装向导&#xff0c;一直Next即可 许可证&#xff1a; https://zhuanlan.zhihu.com/p/685829787#:~:textpro,17%E5%AF%86%E9%92%A5%EF%BC%9AMC60H-DWHD5-H80U9-6…

单词接龙--C++

目录 题目描述 输入格式 输出格式 输入 输出 一、AC代码 二、代码分析 三、vector加深理解 题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏&#xff0c;现在我们已知一组单词&#xff0c;且给定一个开头的字母&#xff0c;要求出以这个字母开头的最长的“…

【LAMMPS学习】八、基本知识的讨论(1.3)从一个输入脚本运行多个模拟

8. 基本知识的讨论 此部分描述了如何使用 LAMMPS 为用户和开发人员执行各种任务。术语表页面还列出了 MD 术语&#xff0c;以及相应 LAMMPS 手册页的链接。 LAMMPS 源代码分发的 examples 目录中包含的示例输入脚本以及示例脚本页面上突出显示的示例输入脚本还展示了如何设置和…

ICLR24_OUT-OF-DISTRIBUTION DETECTION WITH NEGATIVE PROMPTS

摘要 分布外检测&#xff08;OOD Detection&#xff09;的研究对于开放世界&#xff08;open-world&#xff09;学习非常重要。受大模型&#xff08;CLIP&#xff09;启发&#xff0c;部分工作匹配图像特征和提示来实现文本-图像特征之间的相似性。 现有工作难以处理具有与已…

灵活就业人员规模已达2亿人?财会卷王们如何在“卷卷卷”中脱颖而出?

先来看几个数据&#xff1a; 1️⃣2022年全国大学生毕业人数突破1000万&#xff0c;而2023年突破1100万&#xff1b; 2️⃣有超过200万海外留学生&#xff0c;即将回国就业&#xff1b; 3️⃣全国灵活就业人员规模已达2亿人。 &#xff08;图源&#xff1a;互联网&#xff0…

CSS变换

CSS变换 根据 CSS 的变换的功能特性&#xff0c;它可以分为位移、旋转、缩放、倾斜和透视&#xff1a; 也可以分成2D变换和3D变换&#xff0c;2D变换是二维平面上进行的&#xff0c;即 X 轴和 Y 轴。这些变换不涉及 Z 轴。3D 变换允许元素在三维空间中进行操作&#xff0c;这些…

Linux——计算机进程基础知识

计算机基础知识 1.计算机组成五大部件: (1) 运算器 &#xff1a;也叫算数逻辑单元&#xff0c;完成对数据的各种常规运算&#xff0c;如加减乘除&#xff0c;也包括逻辑运算&#xff0c;移位&#xff0c;比较等。 (2) 控制器 &#xff1a; 它是整个计算机系统的控制中心&…

Maven的scope详解

依赖范围介绍 maven 项目不同的阶段引入到classpath中的依赖是不同的&#xff0c;例如&#xff0c;编译时&#xff0c;maven 会将与编译相关的依赖引入classpath中&#xff0c;测试时&#xff0c;maven会将测试相关的的依赖引入到classpath中&#xff0c;运行时&#xff0c;mav…

三星:HBM4的16层堆叠技术验证成功

随着人工智能、大数据分析、云计算及高端图形处理等领域对高速、高带宽存储需求的激增&#xff0c;下一代高带宽内存&#xff08;High Bandwidth Memory, HBM&#xff09;——HBM4已成为全球存储芯片巨头三星、SK海力士和美光竞相追逐的技术高地。 随着AI、机器学习以及高性能…

Linux 5.10 Pstore 功能测试

目录 简介环境配置内核配置参考备注 简介 Pstore(Persistent store support)是用于系统发生oops或panic时&#xff0c;自动保存内核log buffer中的日志。随着功能不断完善&#xff0c;Duo S使用Linux 5.10已经支持保存console日志、ftrace消息和用户空间日志的收集&#xff0c…

JavaScript - 你能说出解决跨域的一些方案吗

难度级别:中高级及以上 提问概率:65% 回答解决跨域之前,首先建议求职者描述什么是跨域。跨域问题是浏览器基于同源策略引起的,同源策略是浏览器的一种安全功能。同源要保证域名相同,或是被访问服务的协议+主机+端口都相同,那么反之这些属…

信阳附大医院-市民心中的健康守护者

信阳附大医院,一所集医疗、预防、保健、科研、教学、康复于一体的现代化综合医院,坐落于信阳市工区路600号,是市卫生部门批准成立的医疗机构,更是市民心中的健康守护者. 医院环境优雅,设施先进,服务周到,汇聚了一支技术精湛、经验丰富的医疗团队.医师们以患者为中心,用心倾听,精…

Hybrid混合开发 和 Android平台JSBridge的原理

书接上篇&#xff1a;移动端研发技术的进化历程 纯原生开发主要面临动态化和开发成本两个问题&#xff0c;而针对这两个问题&#xff0c;诞生了一些跨平台的动态化框架。 针对原生开发面临的问题&#xff0c;业界一直都在努力寻找好的解决方案&#xff0c;而时至今日&#xf…

matlab学习001-简单的矩阵输入及绘制信号曲线

目录 1&#xff0c;熟悉简单的矩阵输入 1.1&#xff0c;创建矩阵 1.2&#xff0c;在命令行调用文件中的变量 1.3&#xff0c;ones函数 1.4&#xff0c;who和whos的使用 2&#xff0c;绘制信号曲线 2.1&#xff0c;实指数信号 2.2&#xff0c;频率为50Hz的周期方波信号…