力扣-回溯法

何为回溯法?

在搜索到某一节点的时候,如果我们发现目前的节点(及其子节点)并不是需求目标时,我们回退到原来的节点继续搜索,并且把在目前节点修改的状态还原。
记住两个小诀窍,一是按引用传状态(&),二是所有的状态修改在递归完成后回改。
回溯法修改一般有两种情况,一种是修改最后一位输出,比如排列组合;一种是修改访问标
记,比如矩阵里搜字符串。

46.全排列

46. 全排列
题目

给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

示例 1:

输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

示例 2:

输入:nums = [0,1]
输出:[[0,1],[1,0]]

示例 3:

输入:nums = [1]
输出:[[1]]

提示:

  • 1 <= nums.length <= 6
  • -10 <= nums[i] <= 10
  • nums 中的所有整数 互不相同​​​​​​​
题解
输出该数组的所有排序组合,我们可以使用回溯法。
首先确定一个位置,然后跟后面的每个位置进行交换。换完之后到下一个位置。然后这一系列步骤结束后,需要将换了的换回来。即回溯法。
class Solution {
public:
    vector<vector<int>> permute(vector<int>& nums) {
        vector<vector<int>> ans;
        back(nums,0,ans);
        return ans;
    }
    void back(vector<int>& nums,int n,vector<vector<int>>& ans){
        int i;
        if(n==nums.size()-1)
            ans.push_back(nums);
        for(i=n;i<nums.size();i++){
            swap(nums[i],nums[n]);
            back(nums,n+1,ans);
            swap(nums[i],nums[n]);
        }
    }
};

77.组合

77. 组合

题目

给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。

你可以按 任何顺序 返回答案。

示例 1:

输入:n = 4, k = 2
输出:
[
  [2,4],
  [3,4],
  [2,3],
  [1,2],
  [1,3],
  [1,4],
]

示例 2:

输入:n = 1, k = 1
输出:[[1]]

提示:

  • 1 <= n <= 20
  • 1 <= k <= n

题解

设定一个count,计算每一个的数量,当count==k时候,就放入数组。这是跟之前不太一样的,之前的是进行排列组合。这个有点像选择排列。

从1-n开始,设置一个额外的数组来存储每一次的结果。count动态变化,将i赋给后count加一,dfs中从(i+1,n)选一个数字。回溯后count--。

class Solution {
public:
    vector<vector<int>> combine(int n, int k) {
        vector<vector<int>> ans;
        vector<int> c(k,0);
        int count;
        dfs(n,k,1,ans,c,count);
        return ans;
    }
    void dfs(int n,int k,int level,vector<vector<int>>& ans,vector<int>& c,int& count){
        int i;

        if(count==k){
            ans.push_back(c);
            return ;
        }
            
        for(i=level;i<=n;i++){
            c[count++]=i;
            dfs(n,k,i+1,ans,c,count);
            --count;
        }
    }
};

79.单位搜索

79. 单词搜索

题目

给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

示例 1:

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出:true

示例 2:

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "SEE"
输出:true

示例 3:

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCB"
输出:false

提示:

  • m == board.length
  • n = board[i].length
  • 1 <= m, n <= 6
  • 1 <= word.length <= 15
  • board 和 word 仅由大小写英文字母组成

题解

类似的套路。

dfs+回溯法,首先定义一个visit,来标记每一次搜索的时候该位置是否被标记过,防止同一个位置被多次访问。

对于一个位置,要进行边界判断,是否越界。接着判断是否已经访问过,是否已经成功找到,是否该位置的字母与目标字母不同。

dfs,往四周搜索。

class Solution {
public:
    bool exist(vector<vector<char>>& board, string word) {
        if(board.empty())
            return false;
        int m=board.size(),n=board[0].size();
        vector<vector<bool>> visit(m,vector<bool>(n,false));
        int i,j;
        bool find=false;
        for(i=0;i<m;i++){
            for(j=0;j<n;j++)
                back(i,j,board,word,find,visit,0);
        }
        return find;
    }
    void back(int i,int j,vector<vector<char>>& board,string& word,
    bool& find,vector<vector<bool>>& visit,int level){
        if(i<0||i>=board.size()||j<0||j>=board[0].size())
            return ;
      
        if(visit[i][j]||find||board[i][j]!=word[level])
            return ;
        if(level==word.size()-1){
            find=true;
            return ;
        }
        visit[i][j]=true;
        back(i+1,j,board,word,find,visit,level+1);
        back(i-1,j,board,word,find,visit,level+1);
        back(i,j+1,board,word,find,visit,level+1);
        back(i,j-1,board,word,find,visit,level+1);
        visit[i][j]=false;
    }
};

51.N皇后

51. N 皇后

题目

按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。

n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。

每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。

示例 1:

输入:n = 4
输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
解释:如上图所示,4 皇后问题存在两个不同的解法。

示例 2:

输入:n = 1
输出:[["Q"]]

提示:

  • 1 <= n <= 9

题意

N皇后,需要三个标记函数,一个是列,一个是主对角线,另外一个是副对角线。

因为每一行肯定会放一个皇后,一行一行遍历,当成功遍历到最后一行并且成功放好皇后即可。所以不需要设行的标记函数。

这个时候我们可以从第一行开始,按列遍历。判断该列是否为false,该主对角线是否为false,副对角线是否为false。如果是则下一列,如果不是就将该位置置为Q,然后对下一行进行同样的寻找。回溯法,找完后记得将位置和标记函数还原。

这个对角线和副对角线。可以画在坐标上,一个为y=x+b,一个为y=-x+b。

所以b=y-x,为了使b>0,因此我们加上n。另外一个为y+x。

class Solution {
public:
    vector<vector<string>> solveNQueens(int n) {
        vector<vector<string>> ans;
        if(n==0)
            return {};
        vector<string> board(n,string(n,'.'));
        vector<bool> c(n,false),l(2*n-1,false),r(2*n-1,false);
        back(n,ans,board,c,l,r,0);
        return ans;
    }
    void back(int n,vector<vector<string>>& ans,vector<string>& board,vector<bool>& c,
    vector<bool>& l,vector<bool>& r,int row){
        if(row==n){
            ans.push_back(board);
            return ;
        }
        int i;
        for(i=0;i<n;i++){
            if(c[i]||l[row-i+n]||r[row+i]){
                continue;
            }
            board[row][i]='Q';
            c[i]=l[row-i+n]=r[row+i]=true;
            back(n,ans,board,c,l,r,row+1);
            board[row][i]='.';
            c[i]=l[row-i+n]=r[row+i]=false;
        }
    }
};

总结

对于回溯法,首先找到边界条件以及结束的条件。一般为设置的i等于行数。

边界条件一般为不要越界。

一般还需要设置标记函数。然后一行一行进行访问或者一个位置一个位置的访问,访问过的标记函数置为true。接着继续下一个或者下一行(一般是递归)。然后结束后还原上面的标记函数以及board(一般会设置一个作为答案)。符合的就push_back到ans数组中去。

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

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

相关文章

阿里云Linux中安装MySQL,并使用navicat连接以及报错解决

首先查询是否安装MySQL // linux 使用yum安装或者rpm安装。(就是一个安装工具类似于applStore&#xff0c;brew不必在意) // 区别&#xff1a;yum会自动安装你要安装的东西的其他依赖&#xff0c;rpm不会但会提示你需要安装的东西&#xff0c;比较麻烦&#xff0c;所以采用yum安…

日常的学习

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;Android ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 正文 7.11 resAndroidManifest 笔记 <> <> selector shape resources main下的AndroidMainifest.xml文件 application …

Windows系统MySQL的安装,客户端工具Navicat的安装

下载mysql安装包&#xff0c;可以去官网下载&#xff1a;www.mysql.com。点击downloads 什么&#xff1f;后面还有福利&#xff1f; 下载MySQL 下载企业版&#xff1a; 下载Windows版 5点多的版本有点低&#xff0c;下载8.0.38版本的。Window系统。下载下面的企业版。不下载…

C++笔试真题

可变分区管理方案 最佳适应&#xff1a;空闲区按容量递增最坏适应&#xff1a;空闲区按容量递减首先适应&#xff1a;空闲区按地址递增 C的结构体中有构造函数。 Linux新建用户或组 useradd&#xff1a;命令用于建立用户账号usermod&#xff1a;修改用户账号groupadd&#…

JAVA中的回溯算法解空间树,八皇后问题以及骑士游历问题超详解

1.回溯算法的概念 回溯算法顾名思义就是有回溯的算法 回溯算法实际上一个类似枚举的搜索尝试过程&#xff0c;主要是在搜索尝试过程中寻找问题的解&#xff0c;当发现已不满足求解条件时&#xff0c;就“回溯”返回&#xff0c;尝试别的路径。回溯法是一种选优搜索法&#xff…

kibana连接elasticsearch(版本8.11.3)

前言 elasticsearch在8版本之后就出现了很大变化&#xff0c;由于kibana版本需要需elasticsearch进行版本对象&#xff0c;kibana连接方式也出现了很大变化。我在这里记录下自己的踩坑记录。 服务部署 本文中的服务都是在docker环境中部署的。其中elasticsearch版本和kibana版…

攻防世界(PHP过滤器过滤)file_include

转换过滤器官方文档&#xff1a;https://www.php.net/manual/zh/filters.convert.php#filters.convert.iconv 这道题因为convert.base64-encode被过滤掉了&#xff0c;所以使用convert.iconv.*过滤器 在激活 iconv 的前提下可以使用 convert.iconv.* 压缩过滤器&#xff0c; 等…

【Python实战因果推断】31_双重差分2

目录 Canonical Difference-in-Differences Diff-in-Diff with Outcome Growth Canonical Difference-in-Differences 差分法的基本思想是&#xff0c;通过使用受治疗单位的基线&#xff0c;但应用对照单位的结果&#xff08;增长&#xff09;演变&#xff0c;来估算缺失的潜…

加减计数器

目录 描述 输入描述&#xff1a; 输出描述&#xff1a; 参考代码 描述 请编写一个十进制计数器模块&#xff0c;当mode信号为1&#xff0c;计数器输出信号递增&#xff0c;当mode信号为0&#xff0c;计数器输出信号递减。每次到达0&#xff0c;给出指示信号zero。 模块的接…

昇思25天学习打卡营第18天|MindNLP ChatGLM-6B StreamChat

MindNLP ChatGLM-6B StreamChat MindNLP ChatGLM-6B StreamChat是基于MindNLP框架和ChatGLM-6B模型实现的聊天应用&#xff0c;利用自然语言处理技术&#xff0c;实现与用户的自然语言交流。这样的应用可以广泛应用于智能客服、在线助理和社交聊天等场景。 在当前技术环境下&a…

鸿蒙语言基础类库:【@ohos.application.testRunner (TestRunner)】 测试

TestRunner TestRunner模块提供了框架测试的能力。包括准备单元测试环境、运行测试用例。 如果您想实现自己的单元测试框架&#xff0c;您必须继承这个类并覆盖它的所有方法。 说明&#xff1a; 开发前请熟悉鸿蒙开发指导文档&#xff1a;gitee.com/li-shizhen-skin/harmony-…

法律咨询援助网站

1 项目介绍 1.1 摘要 随着互联网技术的飞速发展&#xff0c;公众对于便捷、高效的法律咨询服务需求日益增长。传统的法律咨询方式已难以满足人们即时性、多样化的咨询需求&#xff0c;促使法律咨询援助网站应运而生。这些平台旨在通过数字化手段&#xff0c;为用户提供法律知…

教务管理系统

教务管理系统 For Free 本项目免费获取&#xff0c;获取方式在后台发送教务管理系统。系统的实现比较简单&#xff0c;主要是对数据库的读取和前端数据调用的表格展示&#xff0c;并没有太多的交互&#xff0c;比较适合初学者学习Flask和数据库的使用&#xff0c;所以免费获取…

8626 原子量计数

分析&#xff1a; 1. **读取输入**&#xff1a;首先&#xff0c;我们需要读取输入中的第一行&#xff0c;了解有多少个化学式需要处理。之后&#xff0c;对于每个化学式&#xff0c;我们逐行读取并进行处理。 2. **解析化学式**&#xff1a;对于每个化学式&#xff0c;我们需要…

如何在Ubuntu环境下使用加速器配置Docker环境

一、安装并打开加速器 这个要根据每个加速器的情况来安装并打开&#xff0c;一般是会开放一个代理端口&#xff0c;比如1087 二、安装Docker https://docs.docker.com/engine/install/debian/#install-using-the-convenience-script 三、配置Docker使用加速器 3.1 修改配置…

如何处理 PostgreSQL 中由于表锁定导致的并发访问问题?

文章目录 一、表锁定的类型二、表锁定导致的并发访问问题三、解决方案&#xff08;一&#xff09;使用合适的锁定模式&#xff08;二&#xff09;优化事务处理&#xff08;三&#xff09;避免不必要的锁定&#xff08;四&#xff09;使用索引&#xff08;五&#xff09;监控和分…

Protobuf: 大数据开发中的高效数据传输利器

作为一名大数据开发者&#xff0c;我经常需要处理海量的数据传输和存储。在这个过程中&#xff0c;选择一个高效、可靠的数据序列化工具至关重要。今天&#xff0c;我想和大家分享一下我在项目中使用 Protobuf 的经历。 目录 故事背景Protobuf 简介优点&#xff1a; 实战案例示…

在【Open3D】点云世界中精准定位,绘制立方体标记特定点位

Open3D精准定位点云特定点&#xff0c;绘制醒目立方体标记&#xff0c;提升数据解读效率与直观性。 Open3D是一个开源的跨平台计算机视觉库&#xff0c;它为开发人员提供了一个易于使用且高性能的3D数据处理平台。 # pcd&#xff1a;传入原始点云图 # point1&#xff1a;要进…

【HarmonyOS】获取通讯录信息

【HarmonyOS】获取通讯录信息 一、问题背景&#xff1a; 在Android和IOS中&#xff0c;获取手机通讯录信息的方式&#xff0c;一般是申请通讯录权限后&#xff0c;获得手机所有的通讯录列表信息。 在鸿蒙中&#xff0c;因为权限方式安全性提高的变更&#xff1a;将用户权限限…

springboot 旅游导航系统-计算机毕业设计源码69476

目 录 第 1 章 引 言 1.1 选题背景 1.2 研究现状 1.3 论文结构安排 第 2 章 系统的需求分析 2.1 系统可行性分析 2.1.1 技术方面可行性分析 2.1.2 经济方面可行性分析 2.1.3 法律方面可行性分析 2.1.4 操作方面可行性分析 2.2 系统功能需求分析 2.3 系统性需求分析…