LeetCode-BFS问题

1.Floodfill问题
1.图像渲染问题 [https://leetcode.cn/problems/flood-fill/description/](https://leetcode.cn/problems/flood-fill/description/)
class Solution {public int[][] floodFill(int[][] image, int sr, int sc, int color) {//可以借助另一个数组来完成int rows=image.length;int cols=image[0].length;//默认为一个falseboolean nums2[][]=new boolean[rows][cols];int ret=image[sr][sc];image[sr][sc]=color;nums2[sr][sc]=true;int[] position=new int[]{sr,sc};Queue<int [] > queue=new LinkedList<>();queue.offer(position);while(!queue.isEmpty()) {int size=queue.size();while(size>0) {int [] nums1=queue.poll();int row=nums1[0];int col=nums1[1];if(row-1>=0 && image[row-1][col] ==ret && nums2[row-1][col]==false) {queue.offer(new int[]{row-1,col});nums2[row-1][col]=true;}if(col-1>=0 && image[row][col-1] ==ret && nums2[row][col-1]==false) {queue.offer(new int[]{row,col-1});nums2[row][col-1]=true;}if(col+1<=cols-1 && image[row][col+1] ==ret && nums2[row][col+1]==false) {queue.offer(new int[]{row,col+1});nums2[row][col+1]=true;}if(row+1<=rows-1 && image[row+1][col] ==ret && nums2[row+1][col]==false) {queue.offer(new int[]{row+1,col});nums2[row+1][col]=true;}image[row][col]=color;size--;}}return image;}
}

从一个位置开始将上下左右的连接起来的渲染成color。当我们拿到这道题的时候,可能想不到bfs也就是层序遍历。如果我仔细相想一下如果从一个点开始向周围蔓延,这有可能会想到层序遍历。

从(1,1)这个位置开始,这个位置值设为target,开始向上下左右四个方向遍历,如果值跟target相同就加入队列。但是问题也就来了 ,如果当我们遍历到左边时候,按照以上的说法仍会将右边的值加入到队列中。如下图所示

所以这个时候就初始化一个跟原有的数组一样大,来记录那些地方我们已经走过了,也就是代码上面的nums2数组,当我们加入到队列的时候,设置为true。队列中为一个二元组,是这个元素的横坐标和纵坐标。

2.岛屿数量 https://leetcode.cn/problems/number-of-islands/

class Solution {public int numIslands(char[][] grid) {char ret='1';//代表的是岛屿的标志boolean [][] nums2=new boolean[300][300];int ans=0;Queue<int [] >queue=new LinkedList<>();int rows=grid.length;int cols=grid[0].length;for(int i=0;i<rows;i++) {for(int j=0;j<cols;j++) {if(grid[i][j] == ret && nums2[i][j]==false) {queue.offer(new int []{i,j});nums2[i][j]=true;while(!queue.isEmpty()) {int size=queue.size();while(size>0) {int [] nums1=queue.poll();int row=nums1[0];int col=nums1[1];if(row-1>=0 && grid[row-1][col] ==ret && nums2[row-1][col]==false) {queue.offer(new int[]{row-1,col});nums2[row-1][col]=true;}if(col-1>=0 && grid[row][col-1] ==ret && nums2[row][col-1]==false) {queue.offer(new int[]{row,col-1});nums2[row][col-1]=true;}if(col+1<=cols-1 && grid[row][col+1] ==ret && nums2[row][col+1]==false) {queue.offer(new int[]{row,col+1});nums2[row][col+1]=true;}if(row+1<=rows-1 && grid[row+1][col] ==ret && nums2[row+1][col]==false) {queue.offer(new int[]{row+1,col});nums2[row+1][col]=true;}size--;}}ans++;}}}return ans;}
}

这道题是求连起来的岛屿的数量,也就是层序遍历了几次,统计层序遍历的结果。

这一段代码有一些冗余以及不美观,下面的题目会使用两个数组的形式来控制这个上下左右方向的走向。

3.岛屿的最大面积 https://leetcode.cn/problems/max-area-of-island/description/

class Solution {public int maxAreaOfIsland(int[][] grid) {//感觉还是一样的魔板int rows=grid.length;int cols=grid[0].length;int ret=1;//用来记录岛屿的面积int ans=0;Queue<int [] >queue=new LinkedList<>();boolean [][] nums2=new boolean [50][50];for(int i=0;i<rows;i++) {for(int j=0;j<cols;j++) {if(grid[i][j]==ret && nums2[i][j]==false) {queue.offer(new int[]{i,j});nums2[i][j]=true;int count=0;while(!queue.isEmpty()) {int size=queue.size();count+=size;while(size>0) {int [] nums1=queue.poll();int row=nums1[0];int col=nums1[1];if(row-1>=0 && grid[row-1][col] ==ret && nums2[row-1][col]==false) {queue.offer(new int[]{row-1,col});nums2[row-1][col]=true;}if(col-1>=0 && grid[row][col-1] ==ret && nums2[row][col-1]==false) {queue.offer(new int[]{row,col-1});nums2[row][col-1]=true;}if(col+1<=cols-1 && grid[row][col+1] ==ret && nums2[row][col+1]==false) {queue.offer(new int[]{row,col+1});nums2[row][col+1]=true;}if(row+1<=rows-1 && grid[row+1][col] ==ret && nums2[row+1][col]==false) {queue.offer(new int[]{row+1,col});nums2[row+1][col]=true;}size--;}}ans=Math.max(ans,count);}}}return ans;}
}

统计出岛屿的最大面积,就是在统计出岛屿的时候,再计算一步岛屿的面积,由于一个格子的面积是1。当我们进入到层序遍历的时候,使用count变量依次加上队列中这一层的格子数,注意一个岛屿一般都是有很多层的。进入到下一个岛屿遍历的时候,重新初始化count变量。

4.被围绕的区域 https://leetcode.cn/problems/surrounded-regions/description/

class Solution {int [] dx={1,-1,0,0};int [] dy={0,0,1,-1};public void solve(char[][] grid) {//感觉还是一样的魔板//先遍历周围的模块char tmp='A';int rows=grid.length;if(rows==0) {return;}int cols=grid[0].length;Queue<int [] > queue=new LinkedList<>();for(int i =0;i<cols;i++) {if(grid[0][i]=='O') {queue.offer(new int[] {0,i});grid[0][i]=tmp; }if(grid[rows-1][i]=='O') {queue.offer(new int[]{rows-1,i});grid[rows-1][i]=tmp;}}    for(int i=1;i<rows-1;i++) {if(grid[i][0]=='O') {queue.offer(new int []{i,0});grid[i][0]=tmp;}if(grid[i][cols-1]=='O') {queue.offer(new int[] {i,cols-1});grid[i][cols-1]=tmp;}}while(!queue.isEmpty()) {int [] nums1= queue.poll();int row=nums1[0];int col=nums1[1];for(int k=0;k<4;k++) {int a=row+dx[k],b=col+dy[k];if(a>=0 && a<rows && b>=0 && b<cols && grid[a][b]=='O' ) {queue.offer(new int []{a,b});grid[a][b]=tmp;}}}for(int i =0;i<rows;i++) {for(int j =0;j<cols;j++) {if(grid[i][j]==tmp) {grid[i][j]='O';}else if(grid[i][j]=='O') {grid[i][j]='X';}}}}
}

当我们还是按照上面题目的思想来解决这道题目的话,是行不通的。我们仔细观察题目只要区域中包含有外围的格子他就不是被包围的区域,于是我们先遍历周围的格子将周围相连的格子变成tmp,经过bfs之后再进行遍历数组,将tmp的变成’0’,将’0’变成’X’,正难则反,先将不被包围的区域变成一个tmp,再将被包围的区域变成一个’X’。

2.解决最短路问题
1.迷宫中离入口最近的出口 [https://leetcode.cn/problems/nearest-exit-from-entrance-in-maze/description/](https://leetcode.cn/problems/nearest-exit-from-entrance-in-maze/description/)
class Solution {public int nearestExit(char[][] nums, int[] entrance) {// +表示墙,.表示的是一个可走的路int rows=nums.length;int cols=nums[0].length;int [] dx=new int[] {0,0,1,-1};int [] dy=new int[] {1,-1,0,0};boolean [][] visit=new boolean[rows][cols];int a=entrance[0],b=entrance[1];Queue<int[] > queue=new LinkedList<>();queue.offer(new int[]{a,b});visit[a][b]=true;int ans=0;while(!queue.isEmpty()) {ans++;int size=queue.size();for(int i =0;i<size;i++) {int [] tmp=queue.poll();int row=tmp[0],col=tmp[1];for(int j=0;j<4;j++) {int x=row+dx[j],y=col+dy[j];if(x>=0 && y>=0 && x<rows && y<cols && !visit[x][y] && nums[x][y]=='.') {if(x==0 || x==rows-1 || y==0 || y==cols-1) {return ans;}queue.offer(new int[] {x,y});visit[x][y]=true;}}}}return -1;}
}

这里研究的最短路的问题边权都是为1的最短路问题。这里为什么能用bfs来解决,如下图说明。

以红点出发有四个方向可以走,上下左右四个方向。当然这里我们并没有实际走,只是在逻辑上走。

其实这个过程是将所有的结果给枚举出来,结果就是进行几次层序遍历。当我们碰到一个节点为’.'的时候,此时位置正好为边缘的时候,我们将结果返回。为什么进行几层层序遍历就是最小值呢,是因为我们在一层一层进行遍历,遍历的同时看是否到达出口,如果提前有出口,我们也就提前返回了。

2.最小基因变化 https://leetcode.cn/problems/minimum-genetic-mutation/description/

class Solution {public int minMutation(String start, String end, String[] bank) {if(bank.length==0 || bank==null) {return -1;} if(start==end) {return 0;}// 也就是说当我们在进行变化的时候,只有当是基因库中的才有效Queue<String> queue=new LinkedList<>();//这里使用哈希表来进行记录已经遍历过的Map<String,Boolean> hash=new HashMap<>();for(String str:bank) {hash.put(str,false);}int ans=0;char[] nums={'A','C','G','T'};queue.offer(start);while(!queue.isEmpty()) {int size=queue.size();ans++;while(size>0) {String tmp=queue.poll();for(int i=0;i<tmp.length();i++) {// 每个字符就会对应出4个结果for(int j =0;j<4;j++) {// 这里无法在原有的字符串上面进行更改值String ret= tmp.substring(0,i)+nums[j]+tmp.substring(i+1,8);if(ret.equals(end) && hash.containsKey(ret)) {return ans;}if(hash.containsKey(ret) && hash.get(ret)==false) {queue.offer(ret);hash.put(ret,true);}}}size--;}}return -1;}
}

首先,先创建出一个哈希表用来标志这个基因是否到达过。每个基因的就是一个字符串都是等长的,在每个位置进行变换,于是就有了String ret= tmp.substring(0,i)+nums[j]+tmp.substring(i+1,8);这一行代码。剩下的就是跟之前是一样的,这里的变化必须是基因库的。

3.单词接龙 https://leetcode.cn/problems/om3reC/description/

class Solution {public int ladderLength(String start, String end, List<String> word) {Map<String,Boolean> hash=new HashMap<>();int len=start.length();int ans=1;for(String str : word) {hash.put(str,false);}Queue<String> queue=new LinkedList<>();queue.offer(start);while(!queue.isEmpty()) {ans++;int size=queue.size();while(size>0) {String tmp=queue.poll();for(int i=0;i<len;i++) {for(int j=0;j<26;j++) {char ch=(char)('a'+j);String ret=tmp.substring(0,i)+ch+tmp.substring(i+1,len);if(ret.equals(end) && hash.containsKey(ret)) {return ans;}if(hash.containsKey(ret) && hash.get(ret)==false) {queue.offer(ret);hash.put(ret,true);}}}size--;}}return 0;}
}

这道题跟上面的题是一样,只不过换了一个问法。这里是所以可以使用最短路径解决这道题是因为一个单词可以变换成很多的结果,同时结果单词又能变化成很多单词。

4.为高尔夫比赛砍树 https://leetcode.cn/problems/cut-off-trees-for-golf-event/description/

class Solution {int []dx={-1,1,0,0};int []dy={0,0,-1,1};int ans=0;public int cutOffTree(List<List<Integer>> forest) {if(forest.get(0).get(0)==0) {return -1;}List<int[]> list=new ArrayList<>();int rows=forest.size();int cols=forest.get(0).size();for(int i =0;i<rows;i++) {for(int j=0;j<cols;j++) {if(forest.get(i).get(j)>1) {list.add(new int[]{i,j});}}}//对这个数组进行排序Collections.sort(list, (a, b) -> forest.get(a[0]).get(a[1]) - forest.get(b[0]).get(b[1]));int row=0;int col=0;for(int i=0;i<list.size();i++) {//其实在判断的时候只是要一个位置而已//row和col是刚开始位置,肯定要按照顺序找int temp=bfs(forest,row,col,list.get(i)[0],list.get(i)[1]);if(temp==-1) {return -1;}ans+=temp;row=list.get(i)[0];col=list.get(i)[1];}return ans;       }public int bfs(List<List<Integer>> forest,int row,int col,int targetx,int targety) {if(row==targetx && col==targety) {return 0;}//接下里就是宽度搜索//其实找到最小的位置,但是注意不能通行的地方Queue<int[]> queue=new LinkedList<>();int rows=forest.size();int cols=forest.get(0).size();boolean [][]nums=new boolean[rows][cols];int ret=0;queue.offer(new int []{row,col});nums[row][col]=true;while(!queue.isEmpty()) {int size=queue.size();ret++;while(size>0) {int[] temp=queue.poll();for(int i=0;i<4;i++) {int a=dx[i]+temp[0];int b=dy[i]+temp[1];if(a>=0 && a<rows && b>=0 && b<cols) {if(forest.get(a).get(b)>0 && !nums[a][b]) {if(a==targetx && b==targety) {return ret;}queue.offer(new int[]{a,b});nums[a][b]=true;}}}size--;}}return -1;}
}

首先我们看到题目是要求是从低到高开始砍树,先将所有大于的1位置以二元组的形式,可以使用pair,也可以使用数组的形式加入到数组中。然后对数组进行排序,先从(0,0)位置开始向最小的那个位置开始层序遍历,如果途中我们返回了-1的时候,说明四周遇到了障碍。 boolean [][]nums=new boolean[rows][cols];这个每次调用bfs函数的时候,就创建一次。如下图

当从9到10的时候,同时还会遍历8,1,3,4,6,7这些数字,如果我们将这些数字设置为不能再走了 ,此时返回的结果与预期的结果不同。所以每次进行bfs的时候都重新创建一个nums数组。

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Typora+PicGo+Gitee图床配置教程 自动图片上传

配置步骤 #mermaid-svg-aPUbWs43XR5Rh7vf {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-aPUbWs43XR5Rh7vf .error-icon{fill:#552222;}#mermaid-svg-aPUbWs43XR5Rh7vf .error-text{fill:#552222;stroke:#552222;}#…

养生:开启健康生活的全新篇章

养生是一场关乎生活品质与身心健康的持续修行&#xff0c;从饮食调养到运动锻炼&#xff0c;从睡眠管理到心态塑造&#xff0c;每个环节都对健康有着深远影响。以下为你提供全面且实用的养生指南。 饮食养生&#xff1a;科学膳食&#xff0c;滋养生命 合理的饮食是养生的根基…

Python | 赤道频散关系图

写在前面 写开题报告&#xff0c; 想用个图发现截出来全是糊的。索性自己画了&#xff0c;主要实现的Matsuno&#xff08;1966&#xff09;的赤道波动频散关系图。但是&#xff0c;实在是没有审美&#xff0c;其他文献里都是黑色&#xff0c;这里非要用个紫色&#xff0c;因为…

Nexus 私有仓库 + Nginx 反向代理部署文档

1. 使用 Podman 部署 Nexus 3 podman run --name nexus -d \-p 8081:8081 \-v /data:/nexus-data \-v /etc/localtime:/etc/localtime \-e TZ"Asia/Shanghai" \-e INSTALL4J_ADD_VM_PARAMS"-Xms10240m -Xmx10240m -XX:MaxDirectMemorySize4096m" \docker.…

一.Gitee基本操作

一.初始化 1.git init初始化仓库 git init 用于在当前目录下初始化一个本地 Git 仓库&#xff0c;让这个目录开始被 Git 跟踪和管理。 生成 .git 元数据目录&#xff0c;从而可以开始进行提交、回退、分支管理等操作。 2.git config user.name/user.email配置本地仓库 # 设置…

力扣210(拓扑排序)

210. 课程表 II - 力扣&#xff08;LeetCode&#xff09; 这是一道拓扑排序的模板题。简单来说&#xff0c;给出一个有向图&#xff0c;把这个有向图转成线性的排序就叫拓扑排序。如果有向图中有环就没有办法进行拓扑排序了。因此&#xff0c;拓扑排序也是图论中判断有向无环图…

华为ensp实现跨vlan通信

要在网络拓扑中实现主机192.168.1.1、192.168.1.2和192.168.2.1之间的互相通信&#xff0c;需要正确配置交换机&#xff08;S5700&#xff09;和路由器&#xff08;AR3260&#xff09;&#xff0c;以确保不同网段之间的通信&#xff08;即VLAN间路由&#xff09;。 网络拓扑分析…

热部署与双亲委派

热部署初探与双亲委派机制 一、热部署初探 ​ 热部署就是在不重启服务的情况下&#xff0c;无需重新启动整个应用&#xff0c;就能对代码、配置等进行更新并使新的更改在服务中生效。以下代码可以打破双亲委派机制&#xff0c;利用类加载器的隔离实现热部署。可分为以下三步进…

AWS SNS:解锁高并发消息通知与系统集成的云端利器

导语 在分布式系统架构中&#xff0c;如何实现高效、可靠的消息通知与跨服务通信&#xff1f;AWS Simple Notification Service&#xff08;SNS&#xff09;作为全托管的发布/订阅&#xff08;Pub/Sub&#xff09;服务&#xff0c;正在成为企业构建弹性系统的核心组件。本文深度…

驱动开发硬核特训 · Day 30(下篇): 深入解析 lm48100q I2C 音频编解码器驱动模型(基于 i.MX8MP)

作者&#xff1a;嵌入式Jerry 视频教程请关注 B 站&#xff1a;“嵌入式Jerry” 一、背景与目标 在本篇中&#xff0c;我们围绕 TI 的 lm48100q 音频编解码器 展开&#xff0c;深入讲解其作为 I2C 外设如何集成至 Linux 内核音频子系统&#xff08;ASoC&#xff09;&#xff0…

idea写spark程序

步骤 1&#xff1a;创建 Maven 项目 打开 IntelliJ IDEA&#xff0c;选择 File > New > Project。选择 Maven&#xff0c;勾选 Create from archetype&#xff0c;选择 org.apache.maven.archetypes:maven-archetype-quickstart。填写 GroupId&#xff08;如 com.exampl…

【C语言练习】032. 编写带参数的函数

032. 编写带参数的函数 032. 编写带参数的函数1. 定义带参数的函数示例1:定义一个带参数的函数输出结果2. 传递多个参数示例2:定义一个带多个参数的函数输出结果3. 传递数组作为参数示例3:定义一个带数组参数的函数输出结果4. 传递结构体作为参数示例4:定义一个带结构体参数…

Java虚拟机的基本结构

jvm它包含以下部分 第一个&#xff1a;类加载系统 类加载子系统&#xff0c;负责类的加载。类加载器有三种类型&#xff1a;引导类加载器、扩展类加载器、应用程序类加载器。 第二个&#xff1a;运行时数据区 包含了程序计数器、Java虚拟机栈、本地方法栈、堆 、方法区。 程…

uniapp引入七鱼客服微信小程序SDK

小程序引入七鱼sdk 1.微信公众平台引入2.代码引入3.在pagesQiyu.vue初始化企业appKey4.跳转打开七鱼客服 1.微信公众平台引入 账号设置->第三方设置->添加插件->搜索 QIYUSDK ->添加 2.代码引入 在分包中引入插件 "subPackages": [{"root":…

手撕算法(定制整理版2)

最长无重复子字符串 class Solution(object):def lengthOfLongestSubstring(self, s):""":type s: str:rtype: int"""if not s:return 0max_len 0tp []for a in s:while a in tp:del tp[0]tp.append(a)if len(tp) > max_len:max_len len(…

数字IC后端培训教程之数字后端项目典型案例分析

今天给大家分享下最近小编帮助学员解决的几个经典数字IC后端项目问题。希望能够对大家的学习和工作有所帮助。 数字IC后端项目典型问题之后端实战项目问题记录&#xff08;2025.04.24&#xff09; 数字IC后端设计实现培训教程&#xff08;整理版&#xff09; Q1: 老师好&…

window 显示驱动开发-将虚拟地址映射到内存段(二)

在将虚拟地址映射到段的一部分之前&#xff0c;视频内存管理器调用显示微型端口驱动程序的 DxgkDdiAcquireSwizzlingRange 函数&#xff0c;以便驱动程序可以设置用于访问可能重排的分配位的光圈。 驱动程序既不能将偏移量更改为访问分配的 PCI 光圈&#xff0c;也不能更改分配…

Termius ssh连接服务器 vim打开的文件无法复制问题

你的问题是&#xff1a; • 在 Termius (macOS) SSH 连接到 VMware Ubuntu&#xff0c;使用 vim 打开 .cpp 文件时&#xff0c;可以复制文本&#xff1b; • 但在 Windows 10 上 SSH 到 VMware 的 Red Hat 6.4 时&#xff0c;复制操作无效。 ⸻ &#x1f3af; 初步分析 复制…

杨校老师项目之基于SSM与JSP的鲜花销售系统-【成品设计含文档】

基于SSMJSP鲜花商城系统 随着电子商务的快速发展&#xff0c;鲜花在线销售已成为一种重要的消费模式。本文设计并实现了一个基于JSP技术的鲜花销售管理系统&#xff0c;采用B/S架构&#xff0c;使用SSM框架进行开发&#xff0c;并结合Maven进行项目依赖管理。系统分为前台用户模…

集成学习——Bagging,Boosting

一.什么是集成学习 集成学习的基本思想是通过结合多个基学习器的预测结果&#xff0c;来提高模型的泛化能力和稳定性。这些基学习器可以是相同类型的算法&#xff0c;也可以是不同类型的算法。 当基学习器之间具有一定的差异性时&#xff0c;它们在面对不同的样本子集或特征子…