算法学习 | 深度优先搜索~一条道走到黑

news2025/7/21 4:21:00

目录

员工的重要性

图像渲染 

岛屿的周长 

被围绕的区域

岛屿数量 


 

深度优先搜索(Depth First Search):深度优先搜索属于图算法的一种,其过程主要是对每一个可能的分支路径深入到不能再深入到为止,而且每个节点只能访问一次。深度优先搜索本质上就是暴力搜索,遍历了所有可能的情况,必然能得到解。DFS搜索的流程是一个树的形式,每次一条路走到黑。

深度优先搜索的关键是解决“当下该如何做”,下一步的做法和当下的做法是一致的。“当下如何做”一般是尝试每一种可能,用for循环遍历对于每一种可能确定之后,继续走下一步,当前的剩余可能等到从下一步回退之后再处理。据此可以抽象出深度优先搜索的模型

dfs(当前这一步的处理逻辑) {
    1.判断边界,是否已经一条道走到黑:回退
    2.尝试当下的每一种可能
    3.确定一种可能之后,继续下一步dfs(下一步)
}

员工的重要性

题目链接:leetcode-690.员工的重要性

示例

输入:[[1, 5, [2, 3]], [2, 3, []], [3, 3, []]], 1

输出:11

描述:员工1自身的重要度是 5,他有两个直系下属 2 和 3 ,而且 2 和 3 的重要度均为 3 。因此员工 1 的总重要度是 5 + 3 + 3 = 11 。

题目分析

根据题意,可以根据给定的员工id找到员工,从该员工开始遍历,对于每个员工,将其重要性相加,然后再对该员工的每个下属进行遍历,直到所有下属遍历完毕,此时的总和就是给定id的员工及他所有下属的重要度之和。由于每个员工的编号都不同,可以使用哈希表存储员工编号和对应员工,通过员工编号可以找到对应员工

class Solution {
    public int getImportance(List<Employee> employees, int id) {
        if (employees.isEmpty()) {
            return 0;
        }
        Map<Integer, Employee> info = new HashMap<>();
        for (Employee e : employees) {
            info.put(e.id, e);
        }
        return dfs(info, id);
    }
    private int dfs(Map<Integer, Employee> info, int id) {
        Employee curE = info.get(id);
        int sumE = curE.importance;
        for (int curId : curE.subordinates) {
            sumE += dfs(info, curId);
        }
        return sumE;
    }
}

图像渲染 

题目链接:leetcode-773.图像渲染

 

示例 

输入:image = [[1,1,1],[1,1,0],[1,0,1]],sr = 1, sc = 1, newColor = 2

输出:[[2,2,2],[2,2,0],[2,0,1]]

 

题目分析: 

本题的意思是给定一个二维数组表示的图画,并给定一个初始位置和修改后的颜色数字,从初始位置开始,遍历它的上下左右,如果值与初始位置的值相等,就进行修改,一直到遍历完所有符合条件的结点为止.

class Solution {
    int[][] nextPosition = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
    public int[][] floodFill(int[][] image, int sr, int sc, int color) {
        if (image == null || image.length == 0) {
            return new int[0][0];
        }
        int flag = image[sr][sc];
        if (flag != color) {
            dfs(image, sr, sc, color, flag);
        }
        // dfs(image, sr, sc, color, flag);
        return image;
    }
    private void dfs(int[][] image, int sr, int sc, int color, int flag) {
        if (image[sr][sc] == flag) {
            image[sr][sc] = color;
            for (int i = 0; i < 4; i++) {
                int newSr = sr + nextPosition[i][0];
                int newSc = sc + nextPosition[i][1];
                if (newSr >= 0 && newSr < image.length && newSc >= 0 && newSc < image[0].length) {
                    dfs(image, newSr, newSc, color, flag);
                }
            }
        }
    }
}

岛屿的周长 

题目链接:leetcode-463.岛屿的周长

示例 

输入:grid = [[0,1,0,0],[1,1,1,0],[0,1,0,0],[1,1,0,0]]

输出:16

题目分析

根据题意,每次遍历到陆地时,先判断其是否处于边界,如果处于上下左右四个边界,则周长+1,如果不处于边界,就判断其上下左右是否为海洋,如果为海洋,则周长+1,如果为陆地,则不进行操作,每遍历一个陆地后,将其标记出来,下次如果又到了这块陆地,就返回。

class Solution {
    int[][] nextPosition = { {1, 0}, {-1, 0}, {0, 1}, {0, -1} };
    int ret;
    public int islandPerimeter(int[][] grid) {
        if (grid == null || grid.length == 0) {
            return 0;
        }
        int m = grid.length;
        int n = grid[0].length;
        int[][] book = new int[m][n];
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[0].length; j++) {
                if (grid[i][j] == 1) {
                    dfs(grid, book, i, j, m, n);
                    break;
                }
            }
        }
        return ret;
    }
    private void dfs(int[][] grid, int[][] book, int row, int col, int m, int n) {
        if (row < 0 || row >= m || col < 0 || col >= n || grid[row][col] == 0) {
            ret++;
            return ;
        }
        if (book[row][col] == 1) {
            return ;
        }
        book[row][col] = 1;
        for (int i = 0; i < 4; i++) {
            int newRow = row + nextPosition[i][0];
            int newCol = col + nextPosition[i][1];
            dfs(grid, book, newRow, newCol, m, n);
        }
    }
}

被围绕的区域

题目链接:leetcode-130.被围绕的区域

 

例如

输入:board = [["X","X","X","X"],["X","O","O","X"],["X","X","O","X"],["X","O","X","X"]]

输出:[["X","X","X","X"],["X","X","X","X"],["X","X","X","X"],["X","O","X","X"]]

题目分析

 由题意分析可知,只要其他的O与边界上的O相连,就不能被更换,因此,从四个边界的O符号开始,每次判断它的上下左右,只要与边界相连,就将其暂时设为*,接下来从这个*开始,继续寻找它的上下左右,直至到边界值为止,这里的边界值即超越矩阵范围或者遇到X为止.

注意

        if (board[x][y] == '*') {
            return ;
        }

该判断语句一定要加上,否则当遇到*时,就会一直陷入死循环

class Solution {
    public void solve(char[][] board) {
        if (board == null || board.length == 0) {
            return ;
        }
        int m = board.length;
        int n = board[0].length;
        for (int i = 0; i < m; i++) {
            if (board[i][0] == 'O') {
                dfs(board, i, 0);
            }
            if (board[i][n - 1] == 'O') {
                dfs(board, i, n - 1);
            }
        }
        for (int i = 1; i < n - 1; i++) {
            if (board[0][i] == 'O') {
                dfs(board, 0, i);
            }
            if (board[m - 1][i] == 'O') {
                dfs(board, m - 1, i);
            }
        }
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (board[i][j] == 'O') {
                    board[i][j] = 'X';
                }
                if (board[i][j] == '*') {
                    board[i][j] = 'O';
                }
            }
        }
    }
    private void dfs(char[][] board, int x, int y) {
        if (x < 0 || y < 0 || x >= board.length || y >= board[0].length || board[x][y] == 'X') {
            return ;
        }
        if (board[x][y] == '*') {
            return ;
        }
        board[x][y] = '*';
        dfs(board, x + 1, y);
        dfs(board, x - 1, y);
        dfs(board, x, y + 1);
        dfs(board, x, y - 1);       
    }
}

岛屿数量 

题目链接:leetcode-200.岛屿数量

 

例如

输入:grid = [
  ["1","1","1","1","0"],
  ["1","1","0","1","0"],
  ["1","1","0","0","0"],
  ["0","0","0","0","0"]
]

输出: 1

题目分析

对于该题,从任意一个陆地出发,一直遍历它的上下左右,直至四周都是边界或海洋为止,对于每个遍历到过的陆地都将其标记出来,遍历整个二维数组,将每一个未标记过的陆地都作为起点遍历一遍。每次结束之后岛屿数量+1,直至所有陆地都被标记过后为止

代码

class Solution {
    public int numIslands(char[][] grid) {
        if (grid == null || grid[0].length == 0) {
            return 0;
        }
        int m = grid.length;
        int n = grid[0].length;
        int[][] book = new int[m][n];
        int ret = 0;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == '1' && book[i][j] == 0) {
                    dfs(grid, book, i, j);
                    ret++;
                }
            }
        }
        return ret;
    }
    private void dfs(char[][] grid, int[][] book, int x, int y) {
        if (x < 0 || y < 0 || x >= grid.length || y >= grid[0].length || grid[x][y] == '0') {
            return ;
        }
        if (book[x][y] == 1) {
            return ;
        }
        book[x][y] = 1;
        dfs(grid, book, x + 1, y);
        dfs(grid, book, x - 1, y);
        dfs(grid, book, x, y + 1);
        dfs(grid, book, x, y - 1);
    }
}

 

 

 

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

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

相关文章

[毕业设计]机器学习的运动目标跟踪-opencv

目录 前言 课题背景和意义 实现技术思路 第一步&#xff1a;创建单目标追踪器 第二步&#xff1a;读取视频的第一帧 第三步&#xff1a;在第一帧中定位物体 第四步&#xff1a;初始化多目标追踪器 实现效果图样例 前言 &#x1f4c5;大四是整个大学期间最忙碌的时光,一边…

leetcode 907. Sum of Subarray Minimums(子数组最小值的和)

所有子数组的最小值求和。 思路&#xff1a; 最容易想到的就是用DFS找出所有子数组&#xff0c;然后每个子数组找最小值&#xff0c;再求和。但显然不是最优的。 因为费尽心思找到了一堆子数组&#xff0c;它们的最小值竟然是相同的&#xff0c; 是不是有种直接用这个最小值乘…

Alkyne-PEG-Biotin,Alk-PEG-Biotin,炔烃-聚乙二醇-生物素试剂供应

英文&#xff1a;Alkyne-PEG-Biotin&#xff0c;Alk-PEG-Biotin 中文&#xff1a;炔烃-聚乙二醇-生物素 CAS编号&#xff1a;N/A 所属分类&#xff1a;Alkyne PEG Biotin PEG 分子量&#xff1a;可定制&#xff0c;生物素-聚乙二醇5-炔烃、生物素-PEG 20-炔烃 、Biotin-PEG…

HCIA 访问控制列表ACL

一、前言 ACL又称访问控制列表&#xff0c;其实这个东西在很多地方都有用&#xff0c;可能名字不太一样但原理和功能都差不太多&#xff0c;比如服务器、防火墙&#xff0c;都有类似的东西&#xff0c;功能其实也就是“过滤”掉不想收到的数据包。为什么不想收到一些数据包呢&…

C++ 测试框架 Gtest学习——qt版本

目录标题一、参考文档二、获取Gtest三、使用&#xff08;一&#xff09;qt项目导入Gtest&#xff08;二&#xff09;修改pro文件&#xff08;三&#xff09;一个简单的例子&#xff08;四&#xff09;EXPECT&#xff08;期望&#xff09;和ASSERT&#xff08;断言&#xff09;介…

ImportError: cannot import name ‘xxx‘ from ‘xxx‘关于python导包的问题

github clone下来的代码&#xff0c;在矩池云跑的好好的&#xff0c;在自己电脑跑却报错。 ImportError: cannot import name ‘helper’ from ‘utils’ (D:\anaconda\envs\TF2.1\lib\site-packages\utils_init_.py) 搜了网上&#xff0c;说加路径 import sys sys.path.appe…

力控关节机器人(关节扭矩传感器力控)

力控机器人本质上属于协作机器人中的一种&#xff0c;其每个关节都带有力矩传感器&#xff1b; [1] 广泛应用在工业、医疗、新零售领域或智能厨房行业。 Franka Emika&#xff1a; 力控机器人每个关节都带有力矩传感器 力矩传感器提供了一种提高机器人力控性能的途径。 更加…

[毕业设计]基于机器视觉的车辆速度检测与识别算法

前言 &#x1f4c5;大四是整个大学期间最忙碌的时光,一边要忙着备考或实习为毕业后面临的就业升学做准备,一边要为毕业设计耗费大量精力。近几年各个学校要求的毕设项目越来越难,有不少课题是研究生级别难度的,对本科同学来说是充满挑战。为帮助大家顺利通过和节省时间与精力投…

面板平滑转换回归(PSTR)分析案例实现

建模过程包括三个阶段&#xff1a;表述&#xff0c;估计和评估&#xff0c;本文帮助用户进行模型表述、估计&#xff0c;进行PSTR模型评估。 最近我们被客户要求撰写关于PSTR的研究报告&#xff0c;包括一些图形和统计输出。 在程序包中实现了集群依赖性和异方差性一致性检验…

电脑删除的照片怎么找回来?总结了四种方法

照片被删除似乎是常有的事情&#xff0c;如果是重要的照片被删了&#xff0c;想要办法恢复才是最重要的。而对于删除的照片您是如何恢复的呢&#xff1f;这里总结了几种恢复方法&#xff0c;根据自己的需要选择恢复方法&#xff0c;不出意料的话&#xff0c;按照下面的方法你将…

以分割栅格为例实现FME模板的方案优化

一、利用FME分割栅格 &#xff08;一&#xff09;问题的产生 对于FME使用者来说&#xff0c;利用FME完成栅格的批量分割是一件极为平常且容易的事情。只需要输入栅格和确定分割方案就可以实现利用FME对栅格数据的分割&#xff0c;再配合FME的“扇出”功能&#xff0c;就能够实…

WebDAV之葫芦儿·派盘+多彩笔记

多彩笔记 支持webdav方式连接葫芦儿派盘。 还记得小时候那款带密码锁的笔记本?有没有好用的笔记app可以将笔记加上密码,不怕小秘密被偷看?推荐朋友们体验下多彩笔记。 多彩笔记是一款简单又精致的记事软件,用户可以在多彩笔记app中存储,编辑,删除或查找记录,对于写作…

干货 | 如何获取Servlet内存马?

前言 对于回显的获取主要是在ApplicationFilterChain类的lastServicedRequest / lastServicedResponse两个属性&#xff0c;是使用的ThreadLocal进行修饰的&#xff0c;并且&#xff0c;在执行请求的过程中&#xff0c;通过反射修改属性值&#xff0c;能够记录下当前线程的req…

CS224W 7 A General Perspective on Graph Neural Networks

目录 A General GNN Framework A single GNN layer 基本形式 Classical GNN Layers: GCN Classical GNN Layers: GraphSAGE Classical GNN Layers: GAT 动机 Attenion Mechanism Multi-head attention Attenion Mechanism的优点 GNN Layer in Practice Stacking Lay…

股票交易接口软件服务涵盖范围有哪些?

通常所说的股票交易接口软件是指量化交易程序员们可以自行查询各大交易网站或交易所的股票历史数据及行情数据的工具&#xff0c;如&#xff1a;实时报价&#xff1b;走势图&#xff1b;价差图&#xff1b;基金、债券、期货、外汇、保险等各类金融数据查询等&#xff0c;进行数…

elasticsearch7.6安装教程及启动常见错误解决方法

elasticsearch就是一个类似数据库用来专门做搜索的一款工具,在大量的搜索条件下,效率很好,可以直接把它当成一个数据库。 1.打开官网 Download Elasticsearch | Elastic,下载历史版本 这里我选择7.6.1 然后点击linux sha 下载,我这里采用迅雷下载到本地后,再利用Xftp上…

【设计模式】装饰器模式( Decorator Pattern)

装饰器模式属于结构型模式&#xff0c;主要解决当系统需要添加新功能&#xff0c;需要向旧类中不断添加新的属性和方法&#xff0c;从而导致整个类的复杂度不断增长的问题。假如新加的代码仅仅是为了满足特定场景下才会执行的需要&#xff0c;那么就没必要全部写在主类中&#…

一个年薪20万软件测试工程师都具备的能力,你有吗?

今天和大家一起来讨论一下一个很火的问题&#xff1a;作为软件测试工程师需要具备哪些实力。 硬实力&#xff1a;学历技术 目前随着社会的发展&#xff0c;各个行业对岗位学历的要求也越来越高&#xff0c;尤其是对于工资水平高的技术岗位。 测试通用技能&#xff1a; 软件…

Revit中参数化弹簧族怎么做?

Revit中参数化弹簧族制作 第一步&#xff1a;新建族&#xff0c;族样板选择 “公制常规模型第二步&#xff1a;在平面视图中&#xff0c;在中心参照平面两端创建两条参照平面&#xff0c;等分标注&#xff0c;赋予其参数“一圈弹簧直径”&#xff0c;如图 1 第三步&#xff1a;…

环糊精-PEG-麦芽糖 maltose-Cyclodextrin 麦芽糖-环糊精

环糊精-PEG-麦芽糖 maltose-Cyclodextrin 麦芽糖-环糊精 英文名称&#xff1a;maltose-Cyclodextrin 别称&#xff1a;环糊精修饰麦芽糖&#xff0c;环糊精-麦芽糖 还可以提供PEG接枝修饰麦芽糖&#xff0c;麦芽糖-聚乙二醇-环糊精Cyclodextrin-PEG-maltose&#xff0c;环糊…