递归算法学习——目标和,组合总和,字母大小写全排列

news/2024/7/20 20:48:13 标签: 算法, 学习, 数据结构, c++, 深度优先

目录

一,目标和

1.题意

2.例子

3.题目接口

4.解题思路及代码

 二,组合总和

1.题意

2.例子

3.题目接口

4.解题思路及代码

三,字母大小写全排列

1.题意

2.例子

3.题目接口

4.解题思路及代码


一,目标和

1.题意

给你一个非负整数数组 nums 和一个整数 target 。

向数组中的每个整数前添加 '+' 或 '-' ,然后串联起所有整数,可以构造一个 表达式 :

例如,nums = [2, 1] ,可以在 2 之前添加 '+' ,在 1 之前添加 '-' ,然后串联起来得到表达式 "+2-1" 。

返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 的数目

2.例子

 

3.题目接口

class Solution {
public:
    int findTargetSumWays(vector<int>& nums, int target) {

    }
};

4.解题思路及代码

举个例子:如果我的数组里面有三个1,我要得到运算结果为1的组合。我们该如何操作呢?画出决策树如下:

从这张图里面我们可以看到,这里只要深度优先搜索就行了。那什么时候回退到上一层呢?答案显而易见,只有走到最后一层才能回退。函数体应该怎么写呢?关注节点,可知道我们在一个节点上有两种选择。别的不说先写代码如下:

class Solution {
public:
    int count;//记录符合条件的情况
    int path;//记录路径上的和

    int findTargetSumWays(vector<int>& nums, int target) {
        dfs(nums,target,0);
        return count;
    }

    void dfs(vector<int>& nums, int target,int pos)
    {
        if(pos == nums.size())
        {
            if(path == target)
            {
                count++;
            }
            return;
        }
        
        path+=nums[pos];//加的情况
        dfs(nums,target,pos+1);
        path-=nums[pos];

        path-=nums[pos];//减的情况
        dfs(nums,target,pos+1);
        path+=nums[pos];

    }
};

这是一个采用了全局变量的写法,但是你会发现这玩意过不了:

所以,我们就得改变一下策略了。这个时候我们就不能用全局变量了,而是改用参数变量,代码如下:

class Solution {
public:
    int count;//记录符合条件的情况

    int findTargetSumWays(vector<int>& nums, int target) {
        dfs(nums,target,0,0);
        return count;
    }

    void dfs(vector<int>& nums, int target,int pos,int path)
    {
        if(pos == nums.size())
        {
            if(path == target)
            {
                count++;
            }
            return;
        }
        
       
        dfs(nums,target,pos+1,path+nums[pos]);//加的情况
       
      
        dfs(nums,target,pos+1,path-nums[pos]);//减的情况
       
    }
};

这样代码就过掉了:

为什么将path变成函数参数后便能过呢?其实原因就是将path改为dfs的参数以后就能够减少+,-的运算了。加减运算在运行时可是很耗时间的。

 二,组合总和

1.题意

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。

candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。 

对于给定的输入,保证和为 target 的不同组合数少于 150 个。

2.例子

3.题目接口

class Solution {
public:
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        
    }
};

4.解题思路及代码

其实这道题和前面我们见过的那道全排列的题的思路差不多。但是,不同点在于:

1.在这道题里面我们每一组的个数是不定的,只要找出的数组值的和可以等于目标值。

2.在这道题里的同一条路径里的同一个数可以重复使用,但是在一条路劲里使用了以后另一条路劲就不能再使用了。

在这里再来说一下递归的结束条件,当加到的和大于或者等于target的时候便可以收网返回了。所以写出的代码如下:

class Solution {
public:
    vector<int>path;
    vector<vector<int>>ret;
    int aim;//来一个aim来作target的全局变量
    int sum;//计算路径上的数值的和

    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        aim = target;//给aim赋值
       dfs(candidates,0);
       return ret;
    }

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

        if(sum>aim)
        {
            return;
        }


        for(int i = pos;i<candidates.size();i++)//当同一层有多个树要遍历时便可以使用for循环
        {
            sum+=candidates[i];
            path.push_back(candidates[i]);
            dfs(candidates,i);//下一层还是从当前位置开始遍历
            sum-=candidates[i];
            path.pop_back();

        }
    }
};

三,字母大小写全排列

1.题意

给定一个字符串 s ,通过将字符串 s 中的每个字母转变大小写,我们可以获得一个新的字符串。返回 所有可能得到的字符串集合 。以 任意顺序 返回输出。

2.例子

3.题目接口

class Solution {
public:
    vector<string> letterCasePermutation(string s) {

    }
};

4.解题思路及代码

首先举个例子,比如s = "a1b2"。先画出决策树如下:

首先,从这个决策树里面可以判断的是我们不会遇到一层要把所有的树遍历一遍的情况。但是在遇到字母时又要考虑两种情况也就是会遇到大小写字母转换的问题。我们的递归结束条件就是当我们每一个path里的节点个数等于原数组时便要结束条件返回到上一层。根据这个思想写出的代码如下:

class Solution {
public:
   string path;//记录路径节点
   vector<string>ret;//记录每一条路径

    vector<string> letterCasePermutation(string s) {
        dfs(s,0);
        return ret;
    }

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

        //不变的情况
        char ch = s[pos];//记录一下,因为元素会在后面被删除掉
        path.push_back(s[pos]);
        dfs(s,pos+1);
        path.pop_back();


        //变的情况
        if(ch>'9'||ch<'0')
        {
            char tmp = change(ch);
            path.push_back(tmp);
            dfs(s,pos+1);
            path.pop_back();
        }
       
    }

    char change(char& ch)//大小写转换函数
    {
        if(ch>='a'&&ch<='z')
        {
            ch = ch-32;
        }

        else
        {
            ch = ch+32;
        }

        return ch;
    }
};


http://www.niftyadmin.cn/n/4998905.html

相关文章

Feign负载均衡写法

Feign主要为了面向接口编程 feign是web service客户端&#xff0c;是接口实现的&#xff0c;而ribbon是通过微服务名字访问通过RestTemplate调用的&#xff0c;如下&#xff1a; 在Feign的实现下&#xff0c;我们只需要创建一个接口并使用注解的方式来配置它&#xff08;类似…

机器学习课后习题 --- 朴素贝叶斯

&#xff08;一&#xff09;单选题 1.假设会开车的本科生比例是15%&#xff0c;会开车的研究生比例是23%。若在某大学研究生占学生比例是20%&#xff0c;则会开车的学生是研究生的概率是多少&#xff1f; A:80%B:16.6% C:23% D:15% 2.下列关于朴素贝叶斯的特点说法错误的是…

软件测试案例 | 某教务管理平台系统的系统测试总结报告

集成测试通过之后&#xff0c;各个模块已经被组装成了一个完整的软件包&#xff0c;这时就需要进行系统测试了。传统的系统测试指的是通过集成测试的软件系统&#xff0c;作为计算机系统的一个重要组成部分&#xff0c;其将与计算机硬件、外部设备、支撑软件等其他系统元素组合…

春秋云镜 CVE-2018-1273

春秋云镜 CVE-2018-1273 Spring-data-commons 远程命令执行漏洞 靶标介绍 Spring Data是一个用于简化数据库访问&#xff0c;并支持云服务的开源框架&#xff0c;Spring Data Commons是Spring Data下所有子项目共享的基础框架。Spring Data Commons 在2.0.5及以前版本中&…

CF1120 D. Power Tree 巧妙的图论转化

传送门 [前题提要]:无 题目描述: 就是给你一棵树,然后每个点有花费,然后你可以选一个点,付费后对这个点的子树的所有叶子结点增减任意权值. 考虑有一个人会给这棵树的所有叶子结点赋值(值我们不知道),输出最小的花费,使得无论它如何赋值,我们使用上述的花 费都能使所有的叶子…

海底光缆走线逻辑

Submarine Cable Map 电信公司Telegeography每年都会发布其海底电缆地图的新版本。这张地图显示了在世界各地传输数据的所有海底电信电缆。2023 年海底电缆地图现已推出。

【Java核心知识】泛型和类型擦除

文章目录 泛型什么是泛型类型限定类型擦除如何在运行时判断泛型具体类型参考链接 泛型 什么是泛型 Java中的泛型是通过定义模板参数来处理一类操作&#xff0c;这类操作并不关心具体传入的参数类型。比如对于add()方法来说&#xff0c;我们可以使两个int相加&#xff0c;也可…

Nginx笔记-vue项目刷新出现404(try_files和index)

目前的nginx.conf配置&#xff1a; ......server{............location /xxx{root /home/userName/dirindex index.html}} 部署是成功了&#xff0c;但是有个问题&#xff0c;就是感觉整个前端不会找uri&#xff0c;按F5或者在浏览器输入url都会404&#xff0c;只从vue默认的…