Java数据结构与算法----搜索篇(DFS与BFS)

news/2024/5/16 23:47:50/文章来源:https://blog.csdn.net/m0_54409739/article/details/129622798

一.概念

DFS(Depth First Search)深度优先搜索 和BFS(Breadth First Search)广度优先搜索 是两种广泛应用于搜索和遍历算法中的基本技术。这两种算法都涉及到搜索数据结构中的节点 。这里我们以二叉树为例,简单地图解一下两者的区别。(当然它们并不止应用于二叉树,这里仅以遍历二叉树为例来讲述两者算法上的逻辑)

1.1.DFS

DFS(Depth First Search)深度优先搜索 ,其算法思想是从二叉树的根结点开始向下探索,尽可能深地搜索到最底层的节点,然后回溯到上一层,依次向上搜索

这是一个二叉树,按照DFS算法的顺序,搜索的路径是1-2-4-5-3-6-7-8。可以看到,在深度优先搜索中,我们从根开始,沿着左子树一直向下搜索,直到找到叶子节点或者没有更多的未探索节点为止。一旦我们找到一个叶节点,我们会回溯到该节点的上一个节点,继续搜索它的右子树,重复这个过程,直到我们找到整个树。接下来我们用一小段代码来实现这个过程

    public void DFS(Tree tree){if(tree != null){System.out.println(tree.val);DFS(tree.left); //遍历左子树DFS(tree.right); //遍历右子树}}
1.2.BFS

BFS是广度优先搜索算法,与DFS相反,它先从根节点开始,遍历每一层的所有节点,然后逐层向下搜索,直到找到目标节点。

在上图中,我们的搜索路径从根节点开始,先访问1,然后向下一层,逐个遍历2和5,然后再向下一层,遍历4、3、7,最后遍历6、8。所以怎么实现这种遍历呢? 我们一般使用队列来实现哦,我们都知道,队列是先进先出的表,bfs的步骤如下:

① 创捷一个队列 queue

② 将根节点1放入queue

③ 弹出queue的队首 tree

④ 如果左右子树非空,将tree的左右子树分别放入队列queue中

⑤ 重复③ ④ 一直到queue为空,得到的顺序就是二叉树的bfs遍历

代码实现如下:

    public static void BFS(Tree tree){Queue<Tree> queue = new LinkedList<>();queue.add(tree);while(!queue.isEmpty()){Tree now = queue.poll();System.out.println(now.val);if(now.left != null){queue.add(now.left);}if(now.right != null){queue.add(now.right);}}}

二.dfs算法例题

2.1.dfs例题1. 逗志芃的暴走

问题描述

  逗志芃是有妹子的现充,但是有时候妹子就是烦恼。因为逗志芃太逗了,所以这段时间妹子对逗志芃发动了技能无理取闹,妹子要去玩很多的景点。由于逗志芃之前抽机花费了太多的时间,不久以后又要微积分考试了,所以现在被妹子搞成暴走状态了。但是妹子永远是上帝,所以逗志芃只能带妹子出去玩,不过为了节约时间,他希望找到一条花费时间最少的一次性游览线路。

输入格式

  第一行1个数n,表示逗志芃所在的城市有多少个景点,接下来是一个n*n的矩阵。a(i,j)表示i号景点到j号景点的路上花费的时间是多少。

  接下来是一个数m,表示逗志芃妹子要去去的景点数目。由于妹子在无理取闹,所以可能会有重复的景点,不过只要去一次就可以了。接下来是m个数,就是妹子要去的景点编号。

输出格式

  一个数,最少的花费时间。

样例输入

3

0 1 2

1 0 3

2 3 0

3

2 3 1

样例输出

3

数据规模和约定

  0<n<=30,0<m<=20,时间<=1000000

题解思路:这道题使用了folyd算法和dfs算法,具体看代码

package 蓝桥杯;import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Scanner;public class 逗志芃的暴走 {private static PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));private static BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));private static boolean is[];private static int num[] ,ans,index ,map[][],n; //要去的地点数组private static void dfs(int pi,int length,int size){if(size == index){ //如果等于个数ans = Math.min(ans, length);return;}if(length > ans){ //如果大于ans了,没必要再找了,因为再找只会更大return;}for(int i = 0;i < index;i++){if(!is[num[i]]){is[num[i]] = true;dfs(num[i],length + map[pi][num[i]],size+1 );  //加上之后递归is[num[i]] = false;}}}public static void main(String[] args) {Scanner cin = new Scanner(System.in);n = cin.nextInt();map = new int[n+1][n+1];for(int i = 1;i<=n;i++){for(int j = 1;j<=n;j++){map[i][j] = cin.nextInt();}}floyd();is = new boolean[n+1];num = new int[n+1];index = 0;int m = cin.nextInt();for(int i = 0;i<m;i++){int pi = cin.nextInt();if(!is[pi]){is[pi] = true;num[index++] = pi;}}ans = Integer.MAX_VALUE; //最短路径Arrays.fill(is,false);dfs(0,0,0);System.out.println(ans);}private static void floyd() {for(int k = 1;k <= n; k++){for(int i = 1;i<=n;i++){for(int j = 1 ;j<= n ;j++){if(map[i][j] > map[i][k] + map[k][j]){map[i][j] = map[i][k] + map[k][j];}}}}}
}
2.2.dfs例题2. 低阶行列式计算

问题描述

  给出一个n阶行列式(1<=n<=9),求出它的值。

输入格式

  第一行给出两个正整数n,p;

  接下来n行,每行n个数,表示行列式,数据保证行列式中每个数绝对值不超过2*10^9。

输出格式

  一个数表示行列式的值,答案对p取余(余数需要是非负数)。

样例输入

2 2

5 -4

2 -1

样例输出

1

部分数据范围

  对于20%的数据n<=2

  对于40%的数据n<=3

  对于100%的数据n<=9,p<=40000。

对于行列式的计算,如果不懂得可以去看一哈线性代数,里面的行列式是这么计算的捏?

我们以这个行列式为例:

= a11a22a33+a12a23a31+a13a21a32−a13a22a31−a12a21a33−a11a23a32

这里的加法和减法是根据逆序对是否为偶数判断的

序号

排列组合

逆序对

1

+a11a22a33

1 2 3

0

2

+a12a23a31

2 3 1

2

3

+a13a21a32

3 1 2

2

4

a13a22a31

3 2 1

3

5

a12a21a33

2 1 3

1

6

a11a23a32

1 3 2

1

也就是说,我们的题目变成了求n的全排列了咯。直接用dfs全排就好啦

需要注意的是,Java的% 会有负数。。。题目要正数的没所以要在最后处理一哈

package 蓝桥杯刷题;import java.util.Scanner;/*** @Author: stukk* @Description: TODO* @DateTime: 2023-03-22 19:57**/
public class 低阶行列式计算 {private static int n;private static long num[][],ans = 0L,p;private static boolean is[];public static void main(String[] args) {Scanner cin = new Scanner(System.in);n = cin.nextInt();p = cin.nextLong();num = new long[n][n];for(int i = 0;i<n;i++){for(int j = 0;j<n;j++){num[i][j] = cin.nextLong();}}is = new boolean[n];dfs(0,0,new int[n]);long answer = ans % p;if(answer >= 0){System.out.println(answer);}else{System.out.println(p + answer);}}private static void dfs(int size,int index,int number[]){if(size == n){long add = 1;for(int i = 0;i<n;i++){add = add % p * num[i][number[i]] % p;add %= p;}if(ok(number)){ans = ans % p + add % p;}else{ans = ans % p - add % p;}return ;}for(int i = 0;i<n;i++){if(!is[i]){number[index] = i;is[i] = true;dfs(size+1,index+1,number);is[i] = false;}}}private static boolean ok(int[] num) {int cnt = 0;for(int i = 0;i<n;i++){for(int j = 0;j<i;j++){if(num[j] > num[i]){cnt ++;}}}if(cnt % 2 == 0){return true; // 加法}else{return false; //减法}}
}
2.3.dfs例题3.单词接龙

问题描述

  单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如 beast和astonish,如果接成一条龙则变为beastonish,另外相邻的两部分不能存在包含关系,例如at 和 atide 间不能相连。

输入格式

  输入的第一行为一个单独的整数n (n<=20)表示单词数,以下n 行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在.

输出格式

  只需输出以此字母开头的最长的“龙”的长度

样例输入

  5

  at

  touch

  cheat

  choose

  tact

  a

样例输出

23

样例说明

  连成的“龙”为atoucheatactactouchoose

这里需要查找两个字符串是不是有重叠的地方:

    private static int find(String p,String s){for(int i = 1;i<s.length() && i < p.length();i++){if(p.substring(p.length()-i,p.length()).equals(s.substring(0,i))){return i;}}return -1;}

然后返回最小的相同长度,然后在dfs中,判断是不是重合,重合的话就加入递归函数中,并且保持每个单词的使用次数要小于2

package 蓝桥杯刷题;import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.PrintWriter;/*** @Author: stukk* @Description: TODO* @DateTime: 2023-03-22 21:22**/
public class 单词接龙 {private static BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));private static int n,ans = 0,is[];private static String str[];public static void main(String[] args) throws Exception{String p = bf.readLine();n = Integer.parseInt(p);str = new String[n];for(int i = 0;i<n;i++){str[i] = bf.readLine();}is = new int[n];char head = bf.readLine().charAt(0);boolean ok = false;for(int i = 0;i<n;i++){if(head == str[i].charAt(0)){ok = true;break;}}if(!ok){System.out.println(0);return ;}dfs(true,head+"");System.out.println(ans);}private static int find(String p,String s){for(int i = 1;i<s.length() && i < p.length();i++){if(p.substring(p.length()-i,p.length()).equals(s.substring(0,i))){return i;}}return -1;}private static void dfs(boolean isHead,String head) {if(isHead){for(int i = 0;i<n;i++){if(head.charAt(0) == str[i].charAt(0) && is[i] < 2){is[i]++;dfs(false, str[i]);is[i]--;}}}else{for(int i = 0;i<n;i++){int pi = find(head,str[i]);if(pi == -1 || is[i] >= 2){continue;}else{is[i] ++;dfs(false,head + str[i].substring(pi));is[i] --;}}}ans = Math.max(head.length(),ans);}
}/*
5
at
touch
cheat
choose
tact
a*/

三、bfs算法例题

3.1.P1135 奇怪的电梯 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

这道题最短路径的问题可以使用bfs来解决,我们先把A楼放入队列中,然后每次从队列中取出队首节点,将它所能到达的点加入队列,并且同时更新按钮次数,如果到了B楼,我们就直接跳出循环,这时候按钮次数就是答案了。

import java.util.LinkedList;
import java.util.Objects;
import java.util.Queue;
import java.util.Scanner;/*** @Author: stukk* @Description: TODO* @DateTime: 2023-03-22 22:26**/
public class Main {private static class stu{int flour; //当前楼层int button; //按钮的次数@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;stu stu = (stu) o;return flour == stu.flour && button == stu.button;}@Overridepublic int hashCode() {return Objects.hash(flour, button);}public stu(int flour, int button) {this.flour = flour;this.button = button;}}public static void main(String[] args) {Scanner cin  =new Scanner(System.in);int n = cin.nextInt();int a = cin.nextInt();int b=  cin.nextInt();int num[] = new int[n+1];for(int i = 1;i <= n;i++){num[i] = cin.nextInt();}Queue<stu> Q = new LinkedList<>();Q.add(new stu(a,0));int ans = -1;boolean is[] = new boolean[n+1];while(!Q.isEmpty()){stu now = Q.poll();if(now.flour == b){ans = now.button;break;}int up = now.flour + num[now.flour];if(up > 0 && up <= n && !is[up]) {is[up] = true;Q.add(new stu(up,now.button+1));}int down = now.flour - num[now.flour];if(down > 0 && down <= n && !is[down]){is[down] = true;Q.add(new stu(down,now.button+1));}}System.out.println(ans);}
}

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

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

相关文章

实验九 TSP问题

《算法设计与分析》实验报告 所在院系 计算机与信息工程学院 学生学号 学生姓名 年级专业 2020级计算机科学与技术 授课教师 彭绪富 学 期 2022-2023学年第一学期 提交时间 2022年10月26日 目 录 实验九-1&#xff1a;TSP问题 一、实验目的与要求 二…

【图解http】

目录了解web及网络基础TCP/IP协议族与HTTP关系密切的协议&#xff1a;IP、TCP和DNS各种协议与HTTP协议的关系URI和URLhttp协议HTTP是不保存状态的协议请求URI定位资源告知服务器意图的HTTP方法持久连接节省通信量HTTP报文编码提升传输速率压缩传输的内容编码分割发送的分块传输…

关于参加新星计划的收获

目录 作者简介 前言 一、新星计划介绍 二、新星计划创作目标 &#xff08;一&#xff09;创作打卡阶段第1周&#xff08;3/13-3/19&#xff09; &#xff08;二&#xff09;创作打卡阶段第2周&#xff08;3/20-3/26&#xff09; 三、参赛文章的构思与创作 &#xff08…

Go map 内存泄露

前言 在Go中, map这个结构使用的频率还是比较高的. 其实在所有的语言中, map使用的频率都是很高的. 之前在使用中, 一直都知道map的内存在元素删除的时候不会回收, 但一直没有仔细的研究为什么. 今天就来好好揣摩揣摩. func main() {m : make(map[int][128]byte)for i : 0; …

2023热门抖音权重查询小程序源码

2023热门抖音权重查询小程序源码 跟抖音上很火的一模一样&#xff0c;小程序适配优化。接口免费。小程序不是网页 修改教程: 1&#xff0c;如果想修改或者去除水印&#xff0c;直接删除或修改“index.html”12&#xff5e;22行 2&#xff0c;如果想修改logo&#xff0c;直接…

“全球首款旗舰”填补行业空白,两轮电动车技术创新为何只看绿源?

作者 | 曾响铃 文 | 响铃说 乒乓作为我们的“国球”&#xff0c;在数不清的体育赛事里书写辉煌战绩&#xff0c;也进一步被国人熟知、热爱。更难能可贵的是“国球”精神&#xff1a;“别人可能练了一千次&#xff0c;而我们却练了一万次”&#xff0c;冠军品质&#xff0c;奋…

MYSQL【基础篇】MYSQL 主要函数

MySQL中的函数主要分为以下四类&#xff1a; 字符串函数、数值函数、日期函数、流程函数 ​MySQL函数是MySQL数据库提供的内部函数。这些内部函数可以帮助用户更加方便的处理表中的数据 MySQL函数可以对表中数据进行相应的处理&#xff0c;以便得到用户希望得到的数据。这些函…

JAVA Session会话 Thymeleaf - 视图模板技术配置步骤

JAVAWebSession会话会话跟踪技术session保存作用域Thymeleaf - 视图模板技术配置过程Session会话 HTTP是无状态的&#xff1a;服务器无法区分这两个请求是同一个客户端发过来的&#xff0c;还是不同的客户端发过来的 现实问题&#xff1a;第一次请求是添加商品到购物车&#x…

C++中的string类【详细分析及模拟实现】

string类 目录string类一、stirng的介绍及使用1.为什么学习string类&#xff1f;2.标准库中的string类2.1 引入&#xff1a;编码2.2 basic_string3.string类的使用3.1 构造函数3.2 遍历string方式1&#xff1a;for循环方式2&#xff1a;范围for4.迭代器4.1 正向迭代器4.2反向迭…

Golang流媒体实战之二:回源

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)&#xff1a;https://github.com/zq2599/blog_demos 本篇概览 今天的实战是流传输过程中的常见功能&#xff1a;回源如下图&#xff0c;lal(源站)和lal(拉流节点)代表两台电脑&#xff0c;上面都部署了lalVLC在…

【蓝桥杯】巧克力

问题描述&#xff1a; 题解分析&#xff1a; 错误思想&#xff1a;本来的想法是先使用低价格的巧克力&#xff0c;并且判断需要吃几块【其中内容比较细】&#xff0c;直接计算即可&#xff0c;但是本题好像不可以用简单的最小价格的贪心来做 正确思路&#xff1a;创建一个结…

【内网安全】 横向移动IPCATSC命令Impacket套件CS插件全自动

文章目录域信息收集-目标&用户&凭据&网络域横向移动-IPC-命令版-AT&schtasks上线配置at < Windows2012 (该版本之前的操作系统使用at命令)补充反向连接上线效果图schtasks >Windows2012(适用于windows2012后的操作系统版本)建立IPC常见的错误代码域横向移…

【MySQL】JDBC---数据库编程

目录JDBC介绍准备工作操作数据库本文介绍 java 如何使用 jdbc 连接数据库以及连接数据库后的基本操作。JDBC介绍 首先来了解 JDBC(Java Database Connectivity)&#xff0c;java数据库连接。是 Java 提供一套用于操作数据库的接口 API&#xff0c;是 Java 中的数据库连接规范&…

Chapter8.2:PID控制器设计及MATLAB_SIMULINK应用

该系列博客主要讲述Matlab软件在自动控制方面的应用&#xff0c;如无自动控制理论基础&#xff0c;请先学习自动控制系列博文&#xff0c;该系列博客不再详细讲解自动控制理论知识。 自动控制理论基础相关链接&#xff1a;https://blog.csdn.net/qq_39032096/category_10287468…

Flink-FinkSQL进阶操作(系统函数,UDF,表聚合函数等,输入kafka,elasticsearch等外部系统)

11.7 函数 11.7.1 系统函数 标量函数 只有数值大小&#xff0c;没有方向的量&#xff0c;行变行 比较函数 逻辑函数 算数函数 字符串函数 时间函数 聚合函数 多行变一行 count(),sum(),rank(),row_number() 11.7.2 自定义函数(UDF) 分类 标量函数&#xff0c;聚合函…

【数据结构】二叉树及相关习题详解

新年新气象! 祝大家兔年 财源滚滚! 万事胜意! 文章目录前言1. 树的一些基础概念1.1 树的一些基本概念1.2 树的一些重要概念2. 二叉树的一些基本概念2.1 二叉树的结构2.2 两种特殊的二叉树3. 二叉树的性质4. 二叉树的存储5. 二叉树的基本操作5.1 构造一棵二叉树5.2 二叉树的遍历…

华为OD机试题【剩余可用字符集】用 Java 解 | 含解题说明

华为Od必看系列 华为OD机试 全流程解析+经验分享,题型分享,防作弊指南华为od机试,独家整理 已参加机试人员的实战技巧华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典本篇题目:剩余可用字符集 题目 给定两个…

杨辉三角形 (蓝桥杯) JAVA

目录题目描述&#xff1a;暴力破解&#xff08;四成&#xff09;&#xff1a;二分法破解&#xff08;满分&#xff09;&#xff1a;题目描述&#xff1a; 下面的图形是著名的杨辉三角形&#xff1a; 如果我们按从上到下、从左到右的顺序把所有数排成一列&#xff0c;可以得到如…

SpringMVC 源码解析 - 请求执行的过程

一、SpringMVC 请求执行的过程 SpringMVC 是一个基于 Spring 框架的 MVC 框架&#xff0c;它简化了 Web 应用程序的开发。采用了前端控制器模式&#xff0c;请求会首先被一个中央控制器 DispatcherServlet 处理&#xff0c;再由其分发到具体的 Controller 进行处理。其中 Spri…

【Spring Cloud Alibaba】6.添加熔断机制(Sentinel)

文章目录简介什么是 Sentinel开始搭建引入依赖和启用Sentinel创建熔断器类并实现对应的 Feign 接口Service指定熔断器实现类# 启动项目测试未启动服务提供者启动服务提供者简介 接下来为我们的服务消费者提供熔断机制&#xff0c;通过Sentinel来实现熔断&#xff0c;本操作先要…