【递归、搜索与回溯】综合练习二

综合练习二

  • 1.组合
  • 2.目标和
  • 3.组合总和
  • 4.字母大小写全排列

在这里插入图片描述

点赞👍👍收藏🌟🌟关注💖💖
你的支持是对我最大的鼓励,我们一起努力吧!😃😃

1.组合

题目链接:77. 组合

题目分析:

在这里插入图片描述
注意这道题结果是不能重复的。如1,2 和 2,1 虽然位置不同但是是同样的组合。
在这里插入图片描述

算法原理:
这样的题我们还是画出决策树,然后根据这棵树把所有细节分析清楚

在这里插入图片描述
每个位置都有4种选择,首先前面被选种的数字后面就不能再选了,如1,2 和2,1只是位置不同数都是一样的,因此还是重复。其次上每一层都是从上一层被选数字的后面一个开始选的。全局变量,一个ret记录最终结果,一个path记录每条路径的结果。递归函数,给一个pos,每一层都从pos位置开始往后选,dfs(pos)回溯 当递归结束往上返回要恢复现场pop掉path最后一个位置元素,剪枝 用pos控制开始的位置就是剪枝,递归出口 当path.size() == k 就可以把path放到ret里,然后结束本次递归。

在这里插入图片描述

class Solution {
    vector<vector<int>> ret;
    vector<int> path;
    int n_,k_;
public:
    vector<vector<int>> combine(int n, int k) {
        n_=n;k_=k;
        dfs(1);
        return ret;
    }

    void dfs(int pos)
    {
        if(path.size() == k_)
        {
            ret.push_back(path);
            return;
        }

        for(int i=pos;i<=n_;++i)
        {
            path.push_back(i);
            dfs(i+1);
            path.pop_back();//恢复现场
        }
    }
};

2.目标和

题目链接:494. 目标和

题目分析:

在这里插入图片描述

给一个数组,对数组每个数字前面添加 + 或者 - ,串联所有数字构成一个表达式,找出表达式和为目标值有多少种情况。

算法原理:
如果前面做过选子集的问题,这道题思想是一模一样的,找子集其中有一张方法是 这个数字 选or不选,这道题就是 这个数字前面 +or-。我们就根据这个画出决策树。
这里的步骤都不说了,和子集哪里的一模一样。最后到叶子节点这条路径的和加起来等于target,就是一种情况。

在这里插入图片描述
这里写代码有两种形式。

  1. path 是全局变量的时候的代码
  2. path 作为参数的代码

可以参考求二叉树所有路径那道题,这道题也是path作为全局变量和作为参数两种不同形式的代码。

path作为全局变量, 需要考虑回溯恢复现场。
path作为参数,不用考虑,因为在递归在向上返回的时候就已经帮助我们回溯恢复现场了。 path作为参数也是有回溯的不过是编译器就可以帮我回溯了。

如果path是一个单独的类型的话,如int类型,你会发现把它放在dfs参数里面写的话,代码比较简洁。如果path是一个数组类型的话,推荐使用全局变量

path作为全局变量的代码

class Solution {
    int ret,path,_target;
public:
    int findTargetSumWays(vector<int>& nums, int target) {
        _target=target;
        dfs(nums,0);
        return ret;
    }

    void dfs(vector<int>& nums,int pos)
    {
        if(pos == nums.size())
        {
            if(path == _target) ++ret;
            return;
        }

        // 加法
        path+=nums[pos];
        dfs(nums,pos+1);
        path-=nums[pos];

        // 减法
        path-=nums[pos];
        dfs(nums,pos+1);
        path+=nums[pos];
    
    }
};

path作为参数的代码

class Solution {
    int ret,_target;
public:
    int findTargetSumWays(vector<int>& nums, int target) {
        _target=target;
        dfs(nums,0,0);
        return ret;
    }

    void dfs(vector<int>& nums,int pos,long path)
    {
        if(pos == nums.size())
        {
            if(path == _target) ++ret;
            return;
        }

        // +
        dfs(nums,pos+1,path+nums[pos]);
        // -
        dfs(nums,pos+1,path-nums[pos]);


    }
};

3.组合总和

题目链接:39. 组合总和

题目分析:
在这里插入图片描述

注意这个数组中的数字,可以无限制重复被选择。但是结果不能有重复的就如下面2,2,3 和 2,3,2是属于同一种组合,只是位置不同罢了。

在这里插入图片描述
算法原理:
暴力枚举所有情况,根据不同的决策树,我们可以写出不同的代码。就比如

  1. 根据每个位置选什么的策略 画决策树
  2. 根据每个数选or不选 画决策树
  3. 考虑每个数用多少个 画决策树

解法一: 根据每个位置选什么的策略 画决策树

每个位置都有三种选择,因为一个数可以被无限制重复选择,所以递归到下一层还可以选。注意3,2 和 2,3 是一样的组合,前面选了后面就不要在选了。并且5,2 和5,3 和2,5 和3,5一样前面选了后面就不要选了。这是一种剪枝情况,还有当一路径的和sum都大于target了就可以结束递归了。这也是一种剪枝情况。

前面我们特别说明一下全局变量的和作为参数的在递归的区别。这里sum求每一条路径的和我们把它作为参数在递归函数中传递,这样每次回溯就不管sum了,而ret和path还是作为全局变量递归函数 我们发现每次都是从本身位置开始往下选,因此 dfs(nums,pos,sum),回溯 sum不用管,path等到递归返回后pop掉最后一个元素,剪枝已经在递归函数中作为pos传递了 ,递归出口 当sum == target 将path放到ret里然后返回,还有一种情况当sum>target不需要往下递归了和pos == nums.size()也不需要往下递归直接返回;
在这里插入图片描述

class Solution {
    vector<vector<int>> ret;
    vector<int> path;
    int aim;
public:
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
            aim=target;
            dfs(candidates,0,0);
            return ret;
    }

    void dfs(vector<int>& candidates,int pos,int sum)
    {
        if(sum >= aim)
        {
            if(sum > aim) return;
            if(sum == aim) ret.push_back(path);
            return;
        }

        for(int i=pos;i<candidates.size();++i)
        {
            path.push_back(candidates[i]);
            dfs(candidates,i,sum+candidates[i]);
            path.pop_back();//恢复现场
        }
    }
};

解法二: 考虑每个数用多少个 画决策树

每个数可以被选择0-n次,当被选择n次的和都大于target就不能选选了,也就是说小于或者等于target的时候可以一直选这个数,然后往下递归也是和上面情况一样。这里有个细节要注意,当递归回去的时候,不要直接把path最后一个位置pop掉,而是等到这个数所有情况都选完了然后在pop掉path最后一个元素,因为这个数可以选1次、两次等等,如果选择一次往下走递归回来了你pop掉了,下一次path.push_back()就要放两个这个数,因为我们不先pop,等到最后这个数所有情况搞完返回上一层我们在把前面加入的所有这个数pop掉。

在这里插入图片描述

class Solution {
    vector<vector<int>> ret;
    vector<int> path;
    int aim;
public:
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
            aim=target;
            dfs(candidates,0,0);
            return ret;
    }

    void dfs(vector<int>& candidates,int pos,int sum)
    {
        if(sum == aim)
        {
            ret.push_back(path);
            return;
        }

        if(sum > aim || pos == candidates.size()) return;

        // 枚举个数
        for(int k = 0; k * candidates[pos] + sum <= aim; k++)
        {
            if(k) path.push_back(candidates[pos]);
            dfs(candidates, pos + 1, sum + k * candidates[pos]);
        }

        // 恢复现场
        for(int k=1;k*candidates[pos]+sum <= aim;++k)
        {
            path.pop_back();
        }
    }
};

4.字母大小写全排列

题目链接:784. 字母大小写全排列

题目描述:

在这里插入图片描述
算法原理:

还是画出决策树,写代码。
对于每个字母我们都有两种选择,要么不变,要么变,小写变大写,大写变小写。对于数字我们不管它。其他的还是和前面的题一模一样。可以用全局path,也可以path当参数用。

在这里插入图片描述

class Solution {
    vector<string> ret;
    string path;
public:
    vector<string> letterCasePermutation(string s) {
        dfs(s,0);
        return ret;
    }

    void dfs(string& s,int pos)
    {
        if(pos == s.size())
        {
            ret.push_back(path);
            return;
        }

        char ch=s[pos];
        // 不改变
        path.push_back(ch);
        dfs(s,pos+1);
        path.pop_back();

        // 变
        if(ch < '0' || ch > '9')
        {
            if(islower(ch)) ch-=32;
            else ch+=32;

            path.push_back(ch);
            dfs(s,pos+1);
            path.pop_back();
        }

    }
};

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

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

相关文章

海康充电桩报文校验TCP校验和

1 TCP校验文档校验文档要求&#xff1a; 校验码描述 校验码计算范围包含包头标识、消息头和消息体&#xff0c;校验算法采用 TCP 和校验&#xff0c;具体规则如下。 将待校验的所有数据分为 16 位的字&#xff08;大端序&#xff09;&#xff0c;如果总长度为奇数个字节&#…

hadoop未授权访问命令执行漏洞复现-vulfocus

1 介绍 Hadoop YARN&#xff08;Yet Another Resource Negotiator&#xff09;的ResourceManager是集群资源管理的核心组件&#xff0c;负责分配和管理集群资源以及调度作业。如果ResourceManager出现未授权访问漏洞&#xff0c;可能允许未经认证的用户访问或操作集群资源&…

Linux DNS域名解析

DNS系统的作用及类型 整个 Internet 大家庭中连接了数以亿计的服务器、个人主机&#xff0c;其中大部分的网站、邮件等服务器都使用了域名形式的地址&#xff0c;如www.google.com、mail.163.com 等。很显然这种地址形式要比使用 64.233.189.147、202.108.33.74的IP地址形式更…

Windows NT 3.5程序员讲述微软标志性“3D管道”屏幕保护程序的起源故事

人们使用屏保程序来防止 CRT 显示器"烧毁"&#xff0c;因为静态图像会永久损坏屏幕。像 3D Pipes 这样的屏保程序能在显示器处于非活动状态时为其提供动画效果&#xff0c;从而保护屏幕并延长其使用寿命。此外&#xff0c;它们还能在用户不使用电脑时为其提供可定制的…

计算机组成原理之存储器(一)

文章目录 存储器概述存储器的分类情况按照存储器在系统中的作用分类按存储介质分类按存取方式分类 主存储器的技术指标 存储器概述 程序的局部性原理&#xff08;构成多级存储系统的依据&#xff09;&#xff1a;在某一个时间段你频繁访问某一局部的存储器地址空间&#xff0c;…

git 配置私人令牌

这里写自定义目录标题 获取私人令牌配置个人令牌 获取私人令牌 在个人设置里点击私人令牌选型&#xff0c;之后生成令牌即可。注意&#xff1a;令牌只会出现一次&#xff0c;务必保存好。 配置个人令牌 个人令牌&#xff1a;3c15c866fa61066212a83c66fd8133ba # 进入项目文…

私有化、源码开放、无限制技术支持,一站式解决企业文档管理痛点

之前有个用户&#xff0c;当时他们需要查找一份两年前某个产品的设计图纸。在公司的文档库&#xff0c;一份份地翻阅&#xff0c;他花费了整整两天时间才找到所需的设计图纸。这种低效的文档查找方式严重影响了工作效率。 这种就是企业内部文档管理的问题&#xff0c;除了这个…

Python私教张大鹏 Vue3整合AntDesignVue之Steps 步骤条

引导用户按照流程完成任务的导航条。 何时使用 当任务复杂或者存在先后关系时&#xff0c;将其分解成一系列步骤&#xff0c;从而简化任务。 案例&#xff1a;步骤条组件 核心代码&#xff1a; <template><a-steps:current"1":items"[{title: Fin…

LogicFlow 学习笔记——10. LogicFlow 进阶 边

我们可以基于 Vue 组件自定义边&#xff0c;可以在边上添加任何想要的 Vue 组件&#xff0c;甚至将原有的边通过样式隐藏&#xff0c;重新绘制。 如 Example3 中所示&#xff1a; 锚点 默认情况下&#xff0c;LogicFlow 只记录节点与节点的信息。但是在一些业务场景下&#…

Transformer模型探索:Hugging Face库实战篇二——模型与分词器解析

注&#xff1a;本系列教程仅供学习使用, 由原作者授权, 均转载自小昇的 博客 。 文章目录 前言模型 加载模型 保存模型 分词器 分词策略 加载与保存分词器编码与解码文本 处理多段文本 Padding 操作 Attention masks直接使用分词器编码句子对 前言 在上一篇文章 《开箱即…

QT(超详细从0开始)

目录 1.2 Qt的优点 2.安装Qt 3.创建项目 4.解读Qt自动生成的代码 ​编辑 5.Qt Designer 6.Qt对象数 7.Qt乱码问题 8.Qt坐标系的认识 9.信号和槽 9.1 connect 9.2 自定义槽函数 9.3 自定义信号 9.4 断开信号链接&#xff08;disconnect&#xff09; 9.5.lambda表…

【尚庭公寓SpringBoot + Vue 项目实战】租约管理(十四)

【尚庭公寓SpringBoot Vue 项目实战】租约管理&#xff08;十四&#xff09; 文章目录 【尚庭公寓SpringBoot Vue 项目实战】租约管理&#xff08;十四&#xff09;1、业务介绍2、逻辑介绍3、接口开发3.1、保存或更新租约信息3.2、根据条件分页查询租约列表3.3、根据ID查询租…

STM32的通用定时器中断编程

如果遇到需要单片机产生严格时序的场景&#xff08;比如DAC输出特定模拟信号&#xff0c;GPIO口控制模拟开关&#xff09;&#xff0c;延时函数可能就无法胜任了。最近在工作时公司上级教会了我使用“令牌”思维&#xff08;中断标志位)编写单片机裸机程序&#xff0c;今天写一…

c++初始化列表(特点),隐式类型转换(示例,explicit关键字)

目录 初始化列表 定义 特点 必须使用初始化列表的成员变量 初始化顺序 隐式类型转换 示例 explicit关键字 初始化列表 Date::Date(const Date& d) {_year d._year;_month d._month;_day d._day; }Date::Date(const Date& d) :_year(d._year),_month(d._mon…

66aix AI生成系统-中文版安装

66aix是一款多功能的AI助手工具&#xff0c;可以帮助您生成独特的内容&#xff0c;美化和修改您的文章内容或&#xff0c;以及生成图像&#xff0c;去除图像背景。同时&#xff0c;它还包括完整功能的语音转换文本系统。 系统要求 PHP PHP 8 Extensions cURL, OpenSSL, mbstrin…

简易版 | 代码生成器(包含插件)

一、代码生成器 先导入依赖 <!-- Mybatis-Plus --> <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.6</version> </dependency><!-- 代码生成器 --…

css之浮动float

float 设计初衷 仅仅是为了实现文字环绕 图文混排效果 特性 包裹 收缩 坚挺 隔绝 也就是BFC(Block Formating content) - “块级格式化上下文” 破坏 高度塌陷&#xff08;浮动使高度塌陷不是bug &#xff0c;而是标准&#xff0c;特性使然&#xff09; 清除浮动 clear 作…

MySQL----事务的隔离级别(附带每一级别实例截图)

先来回顾一下事务并发可能存在的三大问题&#xff1a; 脏读&#xff08;Dirty Read&#xff09;–不能接受 一个事务读取了另一个事务未提交的数据。例如当事务A和事务B并发执行时&#xff0c;当事务A更新后&#xff0c;事务B查询读取到A尚未提交的数据&#xff0c;此时事务A…

矩阵乘法的直觉

矩阵乘法是什么意思&#xff1f; 一种常见的观点是矩阵乘法缩放/旋转/倾斜几何平面&#xff1a; NSDT工具推荐&#xff1a; Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 - 3D模型语义搜…

Django REST framework序列化器详解:普通序列化器与模型序列化器的选择与运用

系列文章目录 Django入门全攻略&#xff1a;从零搭建你的第一个Web项目Django ORM入门指南&#xff1a;从概念到实践&#xff0c;掌握模型创建、迁移与视图操作Django ORM实战&#xff1a;模型字段与元选项配置&#xff0c;以及链式过滤与QF查询详解Django ORM深度游&#xff…