穷举深搜暴搜回溯剪枝(4)

news2025/7/19 4:57:22

一)单词搜索:

直接在矩阵中依次找到特定字符串

79. 单词搜索 - 力扣(LeetCode)

画出决策树,只需要做一个深度优先遍历:

1)设计dfs函数:只需要关心每一层在做什么即可,从这个节点开始,开始去尝试匹配字符串的下一个字符,就是从某一个位置的字符开始,上下左右下标看看能不能匹配下一个字符给定一个节点的位置,上下左右去匹配一个结点的位置,dfs(char[][] board,i,j,s,pos),把原始的矩阵给定,把这个字符的位置,把要匹配字符串,字符串匹配到哪一个位置

2)从i,j位置开始上下左右去搜索word的哪一个字符就可以了

3)boolean返回值代表此次路径的选择是成功还是失败

2)二维矩阵中要注意的细节问题:

在二维矩阵搜索的过程中不能走重复的路,要想解决这个问题,可以有两种方法:

2.1)使用一个和原始矩阵相同规模大小的布尔数组,如果这个字符已经被路径走过了,那么直接修改成true

2.2)直接修改原始矩阵的值,如果某一个字符被走过了,那么直接修改字符为.或者其他标记字符

假设在下面的这个例子中给定我们一个矩阵,给定一个字符串A="AAAA"判断是否可以匹配成功

2.3)当我们第一次成功的匹配到了A字符的时候,将这个A字符标记成true,表示这个字符已经被使用过了,此时想左匹配第二个A字符,当尝试在第二个A字符中匹配第三个A字符的时候,此时是不能再继续想左找第一个A字符了,此时因为第一个A字符已经被使用过了

class Solution {
    public boolean[][] check;
    int row;
    int col;
//利用向量数组一个for循环搞定上下左右四个方向
    int[] dx={0,0,1,-1};
    int[] dy={1,-1,0,0};
 public boolean dfs(char[][] board,String word,int i,int j,int pos){
        if(pos==word.length()) return true;
        //当匹配到最后一个字符之后直接返回
        //接下来向上下走有去匹配word[pos];
        for(int k=0;k<4;k++){
//从这里面开始左每一层所做的事情,从(i,j)下标开始上下左右去匹配pos位置的字符
            int x=i+dx[k];
            int y=j+dy[k];
if(x>=0&&x<row&&y>=0&&y<col&&check[x][y]==false&&board[x][y]==word.charAt(pos))
{
    check[x][y]=true;
    if(dfs(board,word,x,y,pos+1)) return true;
    check[x][y]=false;
}
        }
        return false;//匹配失败在这里面返回说明上下左右都匹配不到想要的字符
    }
//此时如果不加上返回值的话,那么匹配成功也是返回return;
//此时匹配失败也就是说上下左右找不到特定字符也是返回return;此时主函数就不知道最终是返回true还是false的
    public boolean exist(char[][] board, String word) {
//1.先进行计算二维数组的行和列,初始化布尔数组
        this.row=board.length;
        this.col=board[0].length;
        this.check=new boolean[row][col];
//2.现在整个数组中找到字符串中第一个字符出现的位置,然后去尝试匹配下一个字符
        for(int i=0;i<row;i++){
            for(int j=0;j<col;j++){
                if(board[i][j]==word.charAt(0)){
//先进行遍历整个矩阵直到我们找到第一个位置的时候才会向下进行搜索
                    check[i][j]=true;
                    if(dfs(board,word,i,j,1)==true) return true;
//判断从这个位置开始尝试是否正确
                    check[i][j]=false;
                }
            }
        }
//3.代码走到这里说明所有枚举的第一个位置都无法匹配s这个字符串,所以直接返回false
    return false;
    }
}

二)黄金矿工:

算法原理:

1)这个题和上一个题的起始dfs位置是存在着差别的,上一道题必须是从字符串的第一个位置开始才可以进行向下dfs,而这个题从上下左右边界任意位置开始进行dfs都可以

2)开采过的位置不能再挖,0号位置不能再挖

3)枚举所有位置为起点,进行爆搜

1219. 黄金矿工 - 力扣(LeetCode)

class Solution {
    int ret=0;
    int row=0;
    int col=0;
    public boolean[][] check;
    int[] dx={0,0,1,-1};
    int[] dy={1,-1,0,0};
    public void dfs(int[][] array,int i,int j,int glod){
        glod+=array[i][j];
        ret=Math.max(glod,ret);
        for(int k=0;k<4;k++){
            int x=i+dx[k];
            int y=j+dy[k];
if(x>=0&&x<row&&y>=0&&y<col&&!check[x][y]&&array[x][y]!=0){
    check[x][y]=true;
    dfs(array,x,y,glod);
    check[x][y]=false;
}
        }
    }
    public int getMaximumGold(int[][] array) {
        this.row=array.length;
        this.col=array[0].length;
        this.check=new boolean[row][col];
        for(int i=0;i<array.length;i++){
            for(int j=0;j<array[0].length;j++){
                if(array[i][j]==0) continue;
                else{
                    check[i][j]=true;
                    dfs(array,i,j,0);//这个二层循环的目的就是从每一个位置开始开始挖此时能获取到的最大黄金数
                    check[i][j]=false;
                }
            }
        }
    return ret;
    }
}

三)不同路径

算法原理:在矩阵中进行搜索,先找到1的位置,从这个起始位置开始进行深度优先遍历,然后进行判断这条路径是否合法即可,解决方法就是在进行向下递归的过程中使用count变量来记录一下,从起始位置开始记录一下行走步数,到达最终结果之后,再进行对比和实际要走的步数是否相同(整个数组0的个数)

980. 不同路径 III - 力扣(LeetCode)

class Solution {
    //这样处理的目的就是我所走的所有路径的格子数等于总的格子数
    public int step=2;//表示处理第一个数和最后一个数
    public boolean[][] check;
    public int row=0;
    public int col=0;
    public int count=1;//表示处理第一个数
    public int ret=0;
    int[] dx={0,0,1,-1};
    int[] dy={1,-1,0,0};
    public void dfs(int[][] array,int i,int j){
        if(array[i][j]==2){
            if(step==count){
                System.out.println(ret);
               ret++;
            }
         return;
        }
        for(int k=0;k<4;k++){
            int x=i+dx[k];
            int y=j+dy[k];
if(x>=0&&x<row&&y>=0&&y<col&&!check[x][y]&&array[x][y]!=-1){
             check[x][y]=true;
             count++;
             dfs(array,x,y);
             count--;
             check[x][y]=false;
}
        }
    }
    public int uniquePathsIII(int[][] array) {
        this.row=array.length;
        this.col=array[0].length;
        this.check=new boolean[row][col];
//1.先进行处理整个方形格子中的0的个数
        int dx=0;
        int dy=0;
        for(int i=0;i<row;i++){
            for(int j=0;j<col;j++){
                if(array[i][j]==0) step++;
                else if(array[i][j]==1){
                    dx=i;
                    dy=j;
                }
            }
        }
//2.先找到1的位置
      check[dx][dy]=true;
      dfs(array,dx,dy);
    return ret;
    }
}

四)递增子序列

算法原理:

1)这个题的剪枝策略一共有两步:

1.2)在同一层内,相同的元素重复出现的要剪掉

1.3)在每一层内进行枚举,从pos+1的位置开始进行枚举,防止使用到上一层已经使用过的元素

1.3)在本层进行枚举元素的时候,一定要比上一层的最后一个元素要大,但是如果path中没有任何元素,那么就可以放心地向里面添加元素

491. 递增子序列 - 力扣(LeetCode)

class Solution {
    List<List<Integer>> ret=new ArrayList<>();
    List<Integer> path=new ArrayList<>();
    public void dfs(int[] nums,int pos){
        if(path.size()>=2){
            ret.add(new ArrayList<>(path));
        }
HashSet<Integer> set=new HashSet<>();
//将本层的所有元素保存起来,防止重复
        for(int i=pos;i<nums.length;i++){
if((path.size()==0||path.get(path.size()-1)<=nums[i])&&!set.contains(nums[i])){
            path.add(nums[i]);
            set.add(nums[i]);
            dfs(nums,i+1);
            path.remove(path.size()-1);
}
           
        }
    }
    public List<List<Integer>> findSubsequences(int[] nums) {
        dfs(nums,0);
        return ret;
    }
}

五)分割回文串

131. 分割回文串 - 力扣(LeetCode)

1)什么是切割线?startIndex后面应该被切割的字符串的第一个位置,第一个分割线就是在startIndex第一个字符后面的

2)如何表示切割的子串的范围?[startIndex,i],i一开始等于startIndex,此时切割线在i所指向的字符的后面

class Solution {
    List<List<String>> ret=new ArrayList<>();
     boolean[][] dp=null;
    List<String> path=new ArrayList<>();
    public void dfs(String s,int startIndex){
        if(startIndex==s.length()){
            ret.add(new ArrayList<>(path));
            return;
        }
//注意单层递归的逻辑
        for(int i=startIndex;i<s.length();i++){
            if(dp[startIndex][i]==true){
//判断当前选择切割的这一段部分是否是回文串,如果不是回文串,那么当前位置作废,直接进行剪枝操作
                path.add(s.substring(startIndex,i+1));
//此时这个分割线在i+1这个字符的后面
                dfs(s,i+1);
                path.remove(path.size()-1);
            }else{
                continue;
            }
        }
    }
    public List<List<String>> partition(String s) {
//1.首先创建一个dp表,dp[i][j]表示以i位置元素为起点,j位置字符为终点,是否这个子串是一个回文串
this.dp=new boolean[s.length()][s.length()];
 //从下到上,从走向右进行填表
    for(int i=s.length()-1;i>=0;i--){
         for(int j=i;j<s.length();j++){
            if(s.charAt(i)==s.charAt(j)){
                if(i==j) dp[i][j]=true;
                else if(i+1==j) dp[i][j]=true;
                else{
                    dp[i][j]=dp[i+1][j-1];
                 }
           }else{
              dp[i][j]=false;
            }
      }
  }
  //2.然后进行回溯操作
       dfs(s,0);
       return ret;
    }
}

六)复原IP地址

93. 复原 IP 地址 - 力扣(LeetCode)

算法原理:

1)什么是有效的IP地址呢?

1.1)首先这个IP地址的经过逗号分割的单独一个部分可以包含一个0,但是一个数字前面不能出现前导0,就比如说0.011.122.32

1.2)还有经过逗号分割的每一个部分的值都是小于255的,例如192.168.1.455

1.3)如果给定的字符串中出现了非正整数字符的话,那么它本身也是一个非法的IP地址

所以本题我们不光要对字符串进行切割处理,还需要针对切割出来的每一个字符串要做一个合法性的判断

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

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

相关文章

如何配置视频直播点播平台EasyDSS视频服务平台参数,使同一直播间实现重复推流?

EasyDSS视频直播点播平台集视频直播、点播、转码、管理、录像、检索、时移回看等功能于一体&#xff0c;可提供音视频采集、视频推拉流、播放H.265编码视频等功能&#xff0c;分发的视频流可覆盖全终端、全平台。 EasyDSS已创建的直播间可支持重复推流&#xff0c;但为了保证直…

使用Idea导入mybatis dependence时爆红解决方法

<dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.5</version></dependency>如上在pom.xml中配置mybatis的dependence1时出现爆红的情况。 解决方法 找到idea编辑器右侧的maven按钮…

Linux 中的 chroot 命令及示例

Linux/Unix系统中的chroot命令用于更改根目录。Linux/Unix 类系统中的每个进程/命令都有一个称为root 目录的当前工作目录。它更改当前正在运行的进程及其子进程的根目录。 在此类修改的环境中运行的进程/命令无法访问根目录之外的文件。这种修改后的环境称为“ chroot监狱”或…

maven依赖找不到的解决:手动下载、多镜像导入。

maven中央仓库&#xff0c;远在国外&#xff0c;没下载&#xff0c;因为网络原因迟迟下载不下来&#xff0c;所以我们就需要配置一些国内的镜像仓库&#xff0c;来进行jar包的下载。但是阿里的仓库并没有收录中央仓库的全部jar包&#xff0c;因此导致我们有些jar包下载不下来&a…

什么是数据中台,关于数据中台的6问6答6方法

在大数据/数字孪生时代&#xff0c;数据中台已经成为企业治理数据的核心平台。数据中台不仅处理和整合大量数据&#xff0c;还负责数据的存储、管理和保护工作&#xff0c;确保数据的准确性和可用性。数据中台的特点在于其能够提高业务效率&#xff0c;降低成本&#xff0c;增加…

【漏洞复现】深信服科技EDR平台存在任意用户登录漏洞

漏洞描述 深信服终端检测响应平台EDR,通过云网端联动协同、威胁情报共享、多层级响应机制,帮助用户快速处置终端安全问题,构建轻量级、智能化、响应快的下一代终端安全系统。 该EDR系统存在任意用户登录漏洞&#xff0c;攻击者通过漏洞可以登录系统后台并获取服务器的敏感信息…

深入讲解内存分配函数 malloc 原理及实现

任何一个用过或学过C的人对 malloc 都不会陌生。大家都知道malloc可以分配一段连续的内存空间&#xff0c;并且在不再使用时可以通过free释放掉。但是&#xff0c;许多程序员对malloc背后的事情并不熟悉&#xff0c;许多人甚至把malloc当做操作系统所提供的系统调用或C的关键字…

libQGLViewer的编译和使用

文章目录 libQGLViewer的编译和使用1 前言2 libQGLViewer开发环境搭建2.1 Qt Creator的下载安装2.2 libQGLViewer的下载编译2.3 安装Qt Designer 的QGLViewer控件插件&#xff08;可选&#xff09;2.3 关于Qt Designer 的QGLViewer控件插件的一些问题 3 在自己的项目中调用4 总…

苹果macOS 13.5.2正式发布 修复ImageIO进程

9 月 8 日消息&#xff0c;苹果今日向 Mac 电脑用户推送了 macOS 13.5.2 更新&#xff08;内部版本号&#xff1a;22G91&#xff09;&#xff0c;本次更新距离上次发布隔了 21 天。 需要注意的是&#xff0c;因苹果各区域节点服务器配置缓存问题&#xff0c;可能有些地方探测到…

LED屏幕电流驱动设计原理

LED电子显示屏作为户外最大的应用产品&#xff0c;是大型娱乐&#xff0c;体育赛事&#xff0c;广场大屏幕等场所不可或缺的产品&#xff0c;从单双色简单的文字展示到今天的高清全彩&#xff0c;显示屏的技术一直都在进步&#xff0c;全球80%的LED电子显示屏皆产自于中国。显示…

Docker 概念构成

0 概述 构成原理 Docker 客户端(Client)Docker 客户端通过命令行或者其他工具使用 Docker SDK与 Docker 的守护进程通信。Docker 主机(Host)一个物理或者虚拟的机器用于执行 Docker 守护进程和容器。Docker Hub 提供了庞大的镜像集合供使用。一个 Docker Registry 中可以包含多…

小程序代码管理

“微信开发者工具”点击版本管理&#xff0c;然后点击代码管理会打开代码管理网页。 选择对应的项目组。 进来后点击创建项目。 输入git名称&#xff0c;然后选择命名空间&#xff0c;最后创建即可。 在刚才的“微信开发者工具”选择设置&#xff0c;然后添加远程。 输入名称&…

创建vue项目时如何选择代码检测和格式化方案

&#x1f3ff; 前言 我们创建vue项目时&#xff0c;通常会涉及到选择代码检测和格式化方案&#xff0c;该如何挑选适合自己的个性化配置&#xff1f;本文就来谈谈 ESLint 各个模式的编码规范&#xff0c;以便大家根据自身情况进行选取。 选择Linter / Formatter配置: 选项&…

IIS解析漏洞复现

文章目录 漏洞复现总结 漏洞复现 打开虚拟机&#xff0c;在C:\inetpub\wwwroot\8000_test目录下放一个phpinfo.php文件&#xff1a; 在服务器管理器中打开IIS管理器&#xff0c;选择处理映射程序&#xff1a; 点击添加模块映射&#xff1a; 配置映射模板&#xff0c;php文件…

基于SSM的学校运动会信息管理系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

自己设计CPU学习之路——基于《Xilinx FPGA应用开发》

1. 一个32组位宽为32的寄存器堆 框图 代码 regfile.h ifndef __FEGFILE_HEADER__define __REGFILE_HEADER__define HIGH 1b1define LOW 1b0define ENABLE_ 1b0define DISABLE_ 1b1define DATA_W 32define DataBus 31:0define DATA_D 32d…

plt函数显示图片 在图片上画边界框 边界框坐标转换

%matplotlib inline import torch from d2l import torch as d2l读取图片并显示图片 读取图片 image_path ../data/images/cat_dog_new.jpg # 创建画板 figure d2l.set_figsize() image d2l.plt.imread(image_path) d2l.plt.imshow(image);给出一个(x左上角,y左上角,x右下角…

StyleDrop: 谷歌关于图像风格提取的魔法

Overview StyleDropSummaryAbstract1 Introduction2 Related Work3 StyleDrop: Style Tuning for Text-to-Image Synthesis3.1 Preliminary: Muse [4], a masked Transformer for Text-to-Image Synthesis StyleDrop Summary 题目: StyleDrop: Text-to-Image Generation in A…

【clickhouse】ubuntu20安装clickhouse并用DBeaver远程管理

文章目录 1.安装2.配置3.外部连接测试4. 相关概念5.Reference 1.安装 使用Deb安装包 // 添加证书 sudo apt-get install -y apt-transport-https ca-certificates dirmngr sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 8919F6BD2B48D754// 更新软件源…

AD623参考引脚5仿真

结论如图所示 文档对引脚5的描述如下。 In-Amp Output Reference Input. The voltage input establishes the common-mode voltage of the output. 仿真结果比较贴切理解了此段话的含义。 特此记录 anlog 2023年9月8日