当前位置: 首页 > news >正文

DFS深度优先搜索—Java版

递归三要素

  • 递归的定义

  • 递归的拆解

  • 递归的出口

什么时候使用DFS?

  • 深度回溯问题(DFS与回溯区别不大)

  • 二叉树问题

  • 组合、排列问题

  • 找方案问题(解空间是一棵树或者图,需要自行构造图/树)

  • 图的搜索问题/路径/方案/节点 的的排列

不要使用DFS的场景

  • 连通块问题

  • 拓扑排序

  • 一切可以使用BFS解决的问题

组合问题

  • 例如,[1,2,3] 的所有组合为 [] [1] [2] [3] [1,2] [1,3] [2,3] [1,2,3] 共8种 。

    • 问题模型:求出所有满足条件的组合
    • 判断条件:组合中的元素与顺序无关
    • 时间复杂度:2^n
    • 难点:将题目的要求构成图或者树,以本题为例,可以将集合中的元素作为节点,那么如何构建边呢?为了避免出现出现12和21这种重复集合,可以让小数节点指向大数节点形成有向边。如下图所示:

    在这里插入图片描述
    除此之外也可以将其构建成一棵树,小节点指向大节点,如下所示: 在这里插入图片描述

DFS关键模板

    public int def(int x, int y ,int step){if(递归出口/达到目标状态){//进行对应操作return 0;}for (int i = 0; i < n; i++) {//遍历剩下的所有的情况if(visit[i]==0){//未访问x = 下一步更新;y = 下一步更新;visit[i] = 1;def(x,y,step);visit[i] = 0;  //记得回溯还原}}}

46. 全排列

class Solution {int n;List<List<Integer>> res;int[] visit;int[] permu;public void dfs(int[] nums,int step){if(step==n){ //存了10个数达到结束条件List<Integer> arr = new ArrayList<>();for(int a:permu){arr.add(a);}res.add(arr);return ;}for (int i = 0; i < nums.length; i++) {if(visit[i]==0){permu[step] = nums[i];visit[i] = 1;dfs(nums,step+1);visit[i] = 0;  //记得回溯}}}public List<List<Integer>> permute(int[] nums) {n = nums.length;res = new ArrayList<>();visit = new int[n]; permu = new int[n]; //存一个结果dfs(nums,0); //0表示permu中存了0个数return res;}
}

以下题目DFS不一定是好的解法,但是练手深搜是非常合适的。所有,很多时候,其实DFS属于暴力搜索算法,并不是优化算法,但是作为最基础的搜索算法,必须掌握才能在此基础上进行动态规划或者剪枝优化。

386. 字典序排数

class Solution {int[] item;int[] visit;List<Integer> res;public void dfs(int[] nums,int step,int n){if(step==n){for(int a : item){res.add(a);}return;}for (int i = 0; i < n; i++) {if(visit[i]==0){visit[i]=1;item[step] = nums[i];//多了这段中途判断而已if(step>0 && ((item[step-1]+"").compareTo(item[step]+""))>0){visit[i]=0;return;}  dfs(nums,step+1,n);visit[i]=0;}}}public List<Integer> lexicalOrder(int n) {item = new int[n];visit = new int[n];res = new ArrayList<Integer>();int[] arr = new int[n];for (int i = 0; i < n; i++) {arr[i]=i+1;}dfs(arr,0,n);return res;}
}

64. 最小路径和

这是一道非常非常典型的题目,DFS如果要求一个数,例如路径条数、方案数、路径总和等等。需要弄清楚,这个变量作为参数传递还是定义一个变量。如果作为参数传递,就是模板,直接在参数上进行加减操作,不影响该值在此循环的值。如果作为单独变量(第二种解法)需要复原变量,需要 sum -= grid[i+1][j] 复原,或者记录前面的值直接用,两种方法都一样。特别推荐直接将其作为参数进行传递。

import org.junit.Test;
import java.util.List;
public class lc64 {int res;int sum;int visit[][];
//==================第一种写法==================public void dfs(int[][] grid,int i,int j,int summ){if(i==(grid.length-1) && j==grid[0].length-1){res = Math.min(res,summ);}//下走if((i+1)<grid.length && visit[i+1][j]==0){visit[i+1][j]=1;  dfs(grid,i+1,j,summ+grid[i+1][j]);visit[i+1][j]=0; }//右走if((j+1)<grid[0].length && visit[i][j+1]==0){visit[i][j+1]=1;  dfs(grid,i,j+1,summ+grid[i][j+1]);visit[i][j+1]=0; }}//================第二种写法================public void dfs(int[][] grid,int i,int j ){if(i==(grid.length-1) && j==grid[0].length-1){res = Math.min(res,sum);}//下走if((i+1)<grid.length && visit[i+1][j]==0){visit[i+1][j]=1;int temp = sum;sum += grid[i+1][j];dfs(grid,i+1,j );visit[i+1][j]=0;//或者 sum -= grid[i+1][j];sum = temp; // 还原sum; }//右走if((j+1)<grid[0].length && visit[i][j+1]==0){visit[i][j+1]=1;int temp = sum;sum += grid[i][j+1];dfs(grid,i,j+1 );visit[i][j+1]=0;//或者 sum -= grid[i][j+1];sum = temp;// 还原sum;}}public int minPathSum(int[][] grid) {visit = new int[grid.length][grid[0].length];res = Integer.MAX_VALUE;sum = grid[0][0] ;dfs(grid,0,0 );return res;} 
}

其实,这道题也是非常好的记忆化搜索的动态规划例题,如下:

class Solution {int mem[][];public int arrive(int[][] grid,int i,int j){if(i==0 && j==0){return grid[i][j];}int v1 = Integer.MAX_VALUE;int v2 = Integer.MAX_VALUE;if((i-1)>=0 && j>=0 ) {if(mem[i-1][j]==-1){v1 = arrive(grid,i-1,j);mem[i-1][j] = v1;}else {v1 = mem[i-1][j];}}if((j-1>=0) && i>=0){if (mem[i][j-1]==-1){v2 = arrive(grid,i,j-1);mem[i][j-1] = v2;}else{v2 = mem[i][j-1];}}return Math.min(v1,v2)+grid[i][j];}public int minPathSum(int[][] grid) {  //动态规划mem = new int[grid.length][grid[0].length];for (int i = 0; i < grid.length; i++) {for (int j = 0; j < grid[0].length; j++) {mem[i][j] = -1;}}mem[0][0] = grid[0][0];return arrive(grid,grid.length-1,grid[0].length-1);}
}

最后以一道典型DFS题结束本章讲解

200. 岛屿数量

思路:凡是搜到了一个1,就找到了一个岛屿,为了避免重复计算,需要把这个岛(这个岛不是这个图)的所有1改成0,然后继续往下搜。简单说就是看见1就计数+1,然后把这片岛毁了,接着往下走!其实这里不用visit记录是否访问过,因为访问过的会将其标记为0,但是写了无妨!建议按照模板操作!

public class lc200 {int visit[][];public void dfs(char[][] grid,int i , int j){if(grid[i][j]=='0'){//如果是水就不用深入查找了return;}grid[i][j]='0'; //摧毁int[][] dirc = new int[][]{{-1,0},{1,0},{0,-1},{0,1}}; //方向 上下左右for (int k = 0; k < dirc.length; k++) { //往四个方向走int x = dirc[k][0];int y = dirc[k][1];//往x,y指定的方向走,判断符合条件才走if((((i+x)<grid.length)&&(i+x)>=0) &&(((j+y)<grid[0].length) && j+y>=0) &&visit[i+x][j+y]==0){ //这里判断写的复杂,就是边界判断加访问判断visit[i+x][j+y] = 1;if(grid[i+x][j+y]=='1'){dfs(grid,i+x,j+y); //如果还是岛就继续深入}visit[i+x][j+y] = 0;}}}public int numIslands(char[][] grid) {int count = 0;visit = new int[grid.length][grid[0].length];for (int i = 0; i < grid.length; i++) {for (int j = 0; j < grid[0].length; j++) {if(grid[i][j]=='1'){count++;dfs(grid,i,j); //开始毁灭这个岛所有1}}}return count;}
}

推荐LeetCode类似题型

463. 岛屿的周长

思路:这道题只有一个岛屿,所以可以两重循环判断1是否挨着0或者是边界,是的话就算作边,考虑上下左右,加起来就是周长。但是 如果深度搜索呢?一样的,对于每个1都计算与水或者边界相邻的边。

695. 岛屿的最大面积

思路:和统计岛屿数量相同,只不过深度遍历每个岛屿时计算有多少个1,存下来,最后返回最大值即为最大面积的岛屿。

827. 最大人工岛

以上,此题作为思考题!

相关文章:

DFS深度优先搜索—Java版

递归三要素 递归的定义 递归的拆解 递归的出口 什么时候使用DFS&#xff1f; 深度回溯问题&#xff08;DFS与回溯区别不大&#xff09; 二叉树问题 组合、排列问题 找方案问题&#xff08;解空间是一棵树或者图&#xff0c;需要自行构造图/树&#xff09; 图的搜索问题…...

RAY - 小记

文章目录关于 RAYRAY 结构关于 RAY Ray is a unified framework for scaling AI and Python applications. Ray consists of a core distributed runtime and a toolkit of libraries (Ray AIR) for accelerating ML workloads. RAY 是一个简单、通用的分布式计算框架。 RAY 解…...

金三银四软件测试工程师面试题(含答案)

前言&#xff1a;此文专门记载本人平时面试以及收藏的面试题目&#xff0c;如果有错误之处请及时指正&#xff0c;谢谢&#xff01; 1、python的数据类型有哪些 答&#xff1a;Python基本数据类型一般分为&#xff1a;数字、字符串、列表、元组、字典、集合这六种基本数据类…...

Python 连接数据源与邮件功能(九)

文章目录一、概述二、Python 连接数据源1&#xff09;Python MySQL 基础操作1、部署MySQL2、MySQL Connector 库【1】安装 mysql-connector-python 库【2】连接 MySQL【3】增加数据【4】查询数据【5】更新数据【6】删除数据2、PyMySQL 库【1】安装 PyMySQL 库【2】连接 MySQL【…...

网站如何锁定用户,超级浏览器有办法解决吗?

随着全球开放&#xff0c;跨境电商人纷纷开启了2023年的搞钱之旅&#xff0c;很多期待着在新的一年大干一场。但前事不忘后事之师&#xff0c;2022年跨境生意全面沦陷&#xff0c;其实除了大环境的因素之外&#xff0c;还有一个很重要的原因是&#xff0c;各个平台都开始实行非…...

Ubuntu下使用Wine运行HBuilderX

安装完wine后&#xff0c;在HbuilderX的目录中打开终端&#xff0c;直接输入wine HBuilderX.exe命令&#xff0c;启动过程中会提示安装wine-mono组件&#xff0c;点击安装按钮下载安装该组件&#xff0c;该组件下载速度慢&#xff0c;需要等待特别长时间。   安装完毕后&…...

如何高效远程维护分布在海外的中大型智能设备?

一、行业需求 随着越来越多的企业进行全球化经营&#xff0c;设备制造商和系统集成商的设备分布到全球各地&#xff0c;数量多而且分散&#xff0c;传统的设备运维方式&#xff0c;面临着出差成本高&#xff0c;工作效率低&#xff0c;服务不及时等问题&#xff0c;客户常常因…...

【双指针问题】LeetCode 925. 长按键入

Halo&#xff0c;这里是Ppeua。平时主要更新C语言&#xff0c;C&#xff0c;数据结构算法......感兴趣就关注我吧&#xff01;你定不会失望。 &#x1f308;个人主页&#xff1a;主页链接 &#x1f308;算法专栏&#xff1a;专栏链接 我会一直往里填充内容哒&#xff01; &…...

APP测试中IOS和Android的区别,有哪些注意点?

01、常识性区别 02、导航方式 iOS&#xff1a;Tab放在页面底部&#xff0c;不能通过滑动来切换&#xff0c;只能点击。也有放在上面的&#xff0c;也不能滑动&#xff0c;但有些Tab本身可以滑动&#xff0c;比如天猫的。还有新闻类的应用。 Android&#xff1a;一般放在页面…...

2019蓝桥杯真题平方序列(填空题) C语言/C++

题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 小明想找到两个正整数 X 和 Y&#xff0c;满足2019<X<Y;2019^2, X^2, Y^2组成等差数列。 请你求出在所有可能的解中&#xff0c;XY 的最小值是多少&#xff1f…...

vue中,给一个URL地址,利用FileSaver.js插件下载文件到本地

①首先下载 FileSaver.js 插件 npm install file-saver --save ②在需要的.vue页面引入 import { saveAs } from file-saver 在HTML中引入 <script src"https://cdn.bootcdn.net/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"></script> //Fil…...

从0开始学python -34

Python3 输入和输出-2 读和写文件 open() 将会返回一个 file 对象&#xff0c;基本语法格式如下: open(filename, mode)filename&#xff1a;包含了你要访问的文件名称的字符串值。mode&#xff1a;决定了打开文件的模式&#xff1a;只读&#xff0c;写入&#xff0c;追加等。…...

瑞典军事研究:从认知心理学的视角探讨军事创新进程

来源&#xff1a;Military Innovation as the Result of Mental Models of Technology 《摘要》 政治紧张局势的加剧和技术发展的进步促使Scandinavian 国家&#xff08;斯堪的纳维亚半岛&#xff0c;欧洲最大的半岛&#xff0c;有挪威、瑞典两国以及芬兰北端的一小部分。&am…...

【MySQL进阶-08】深入理解innodb存储格式,双写机制,buffer pool底层结构和淘汰策略

MySql系列整体栏目 内容链接地址【一】深入理解mysql索引本质https://blog.csdn.net/zhenghuishengq/article/details/121027025【二】深入理解mysql索引优化以及explain关键字https://blog.csdn.net/zhenghuishengq/article/details/124552080【三】深入理解mysql的索引分类&a…...

5. AOP

一、如何定义一个MethodHandler? 1.Controller注解修饰的类 1.注册成Spring Bean 2.表示它是一个SpringMVC下的Controller 2.在这个类下的方法中&#xff0c;只要被RequestMapping修饰&&方法的形参符合规定&#xff08;需要看文档&#xff09; 方法的返回值符合规定…...

ubuntu上尝试libpqxx库链接人大金仓

ubuntu上尝试libpqxx库链接人大金仓 C的项目让使用国产数据库 运维给架了一个人大金仓数据库&#xff0c; Kingbase 8 是基于 PostgreSQL 9.6 做的&#xff0c; 尝试直接使用libpqxx链接数据库。 文章目录ubuntu上尝试libpqxx库链接人大金仓第一步 搭建libpqxx开发环境搜索lib…...

【Python入门第十二天】Python 列表

Python 集合&#xff08;数组&#xff09; Python 编程语言中有四种集合数据类型&#xff1a; 列表&#xff08;List&#xff09;是一种有序和可更改的集合。允许重复的成员。元组&#xff08;Tuple&#xff09;是一种有序且不可更改的集合。允许重复的成员。集合&#xff08…...

Android 异步操作库 RxJava

RxJava概述 RxJava 是一种响应式编程&#xff0c;来创建基于事件的异步操作库。基于事件流的链式调用、逻辑清晰简洁。 RxJava 我的理解是将事件从起点&#xff08;上游&#xff09;流向终点&#xff08;下游&#xff09;&#xff0c;中间有很多卡片对数据进操作并传递&#x…...

2021-12-05青少年软件编程(C语言)等级考试试卷(六级)解析

2021-12-05青少年软件编程(C语言)等级考试试卷(六级)解析T1. 电话号码 给你一些电话号码,请判断它们是否是一致的,即是否有某个电话是另一个电话的前缀。比如: Emergency 911 Alice 97 625 999 Bob 91 12 54 26 在这个例子中,我们不可能拨通Bob的电话,因为Emergency的…...

github 使用

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录一、git与github二、出错的地方1.GitHub没有css样式2、git clone出现错误3、明明创建了responsibility 但git 不显示一、git与github 这个博客写的很好&#xff01;…...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架&#xff0c;它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用&#xff0c;和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》

引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

MongoDB学习和应用(高效的非关系型数据库)

一丶 MongoDB简介 对于社交类软件的功能&#xff0c;我们需要对它的功能特点进行分析&#xff1a; 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具&#xff1a; mysql&#xff1a;关系型数据库&am…...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设…...

【单片机期末】单片机系统设计

主要内容&#xff1a;系统状态机&#xff0c;系统时基&#xff0c;系统需求分析&#xff0c;系统构建&#xff0c;系统状态流图 一、题目要求 二、绘制系统状态流图 题目&#xff1a;根据上述描述绘制系统状态流图&#xff0c;注明状态转移条件及方向。 三、利用定时器产生时…...

力扣-35.搜索插入位置

题目描述 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...

Yolov8 目标检测蒸馏学习记录

yolov8系列模型蒸馏基本流程&#xff0c;代码下载&#xff1a;这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中&#xff0c;**知识蒸馏&#xff08;Knowledge Distillation&#xff09;**被广泛应用&#xff0c;作为提升模型…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)

RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发&#xff0c;后来由Pivotal Software Inc.&#xff08;现为VMware子公司&#xff09;接管。RabbitMQ 是一个开源的消息代理和队列服务器&#xff0c;用 Erlang 语言编写。广泛应用于各种分布…...

c# 局部函数 定义、功能与示例

C# 局部函数&#xff1a;定义、功能与示例 1. 定义与功能 局部函数&#xff08;Local Function&#xff09;是嵌套在另一个方法内部的私有方法&#xff0c;仅在包含它的方法内可见。 • 作用&#xff1a;封装仅用于当前方法的逻辑&#xff0c;避免污染类作用域&#xff0c;提升…...