代码随想录 | Day28 | 回溯算法:组合组合总和III

news2024/11/27 14:35:41

代码随想录 | Day28 | 回溯算法:组合&&组合总和III

关于这个章节,大家最好是对递归函数的理解要比较到位,听着b站视频课可能呢才舒服点,可以先去搜一搜关于递归函数的讲解,理解,再开始这个章节会比较好一些

我觉得回溯就是对传入递归函数的参数加加减减,加了的减掉,减了的加上

主要学习内容:

组合题目的模板

77.组合

[77. 组合 - 力扣(LeetCode)](https://leetcode.cn/problems/convert-sorted-array-to-binary-search-tree/description/)

解法思路:

首先,把问题转换为树形结构,树的每一层的各个结点都是由本层逻辑的for循环产生的,树的深度是由我们所求集合的大小决定的。

20201123195223940

我们在第一层取出一个数字,第一层就是 1 ,2 ,3 ,4

第二层从剩余的集合中取出一个数字,那就是 [1,2] [1,3] [1,4] …

而我们集合大小为2,那么就只有这两层,树的深度也就这两层

而我们选完[1,2]怎么返回[1]的时候去选择[1,3]呢?

这时候就是回溯算法,回溯就是恢复你选择之前的状态,让你去选择另外一个,本质上是穷举的思想

1.函数参数和返回值

vector<vector<int>> res; 
void backtracking(vector<int> path,int n,int k,int index)

res存放结果,path是当前已经收集的组合,n,k不必说,index表示我们已经选到哪个数字了,防止出现重复的组合

2.终止条件

我们当前收集的集合大小等于要求的大小就收集到最后的结果集中,然后返回,这也是能够控制树的深度只有两层的原因

if(path.size()==k)
{
	res.push_back(path);
	return;
}

3.本层代码逻辑

其实最难理解的就是for循环部分。

由于题目要求的是组合,我们只要防止重复,所以引入index,让index之前的已经选过的数不再出现,比如第一层选了2之后,index会让1和2不再出现,只会出现3,4,不会同时出现[1,2]和[2,1]这两个组合了

对for的理解可以脑补一下,举例比如选了1之后,本层的递归函数index是1

进入for循环,传入的先是2,在树的下一层,产生了[1,2]组合,大小满足2,结束递归返回上层,上层将2弹出,继续下一次循环,传入的就是3,产生了[1,3],以此类推

需要注意的是不要写成index+1,这个是错误的,会出现:在你选完第一层的数字后,不管你第一层选的数是多少,第二层都是从2开始的

错误案例

n=4,k=2

image-20241006172301826

最后递归函数返回来以后,把咱压入的元素再弹出就好

for(int i=index;i<=n;i++)
{
	path.push_back(i);
	backtracking(path,n,k,i+1);//注意不是index+1
	path.pop_back();//回溯,恢复现场
}

完整代码:

class Solution {
public:
    vector<vector<int>> res; 
    void backtracking(vector<int> path,int n,int k,int index)
    {
        if(path.size()==k)
        {
            res.push_back(path);
            return;
        }
        for(int i=index;i<=n;i++)
        {
            path.push_back(i);
            backtracking(path,n,k,i+1);//注意不是index+1
            path.pop_back();
        }
    }
    vector<vector<int>> combine(int n, int k) {
        vector<int> path;
        backtracking(path,n,k,1);
        return res;
    }
};

优化

注意代码中i,就是for循环里选择的起始位置,可以循环的次数少一点。(大家可以看代码随想录中的)

for (int i = startIndex; i <= n; i++) {

接下来看一下优化过程如下:

  1. 已经选择的元素个数:path.size();
  2. 所需需要的元素个数为: k - path.size();
  3. 列表中剩余元素(n-i) >= 所需需要的元素个数(k - path.size())
  4. 在集合n中至多要从该起始位置 : i <= n - (k - path.size()) + 1,开始遍历

为什么有个+1呢,因为包括起始位置,我们要是一个左闭的集合。

举个例子,n = 4,k = 3, 目前已经选取的元素为0(path.size为0),n - (k - 0) + 1 即 4 - ( 3 - 0) + 1 = 2。

从2开始搜索都是合理的,可以是组合[2, 3, 4]。

所以优化之后的for循环是:

for (int i = startIndex; i <= n - (k - path.size()) + 1; i++) // i为本次搜索的起始位置

216.组合总和III

216. 组合总和 III - 力扣(LeetCode)

思路:

思路和上一题一模一样,就是上一题给定的n换成了9,然后多了一个加和的操作

加和的操作你可以等到有3个数以后再加起来进行比较,也可以在递归的过程中累加并且比较

1.函数返回值和参数

vector<vector<int>> res;
void backtracking(vector<int> path,int k,int sum,int n,int index)

res记录结果

path收集当前组合

k组合大小

n总和值

sum当前集合的总和

index从哪个数开始

2.终止条件

当前总和已经大于n了,没必要再递归了

如果大小等于k并且加起来等于n,收集结果,不等于n直接返回

if(sum>n)
	return ;
if(path.size()==k)
{
	if(sum==n)
		res.push_back(path);
	return;
}

3.本层逻辑

优化的思路一样的直接套用了

和上一题不一样的就是多加了一个总和值sum

让sum加上我们压入path的值i传入下层即可,下层函数会在终止条件进行比较。

for(int i=index;i<=9-(k-path.size())+1;i++)
{
	path.push_back(i);
	backtracking(path,k,sum+i,n,i+1);//也可以写成 递归函数前写sum+=i,递归函数后写sum-=i,也可以写在递归函数参数中,比如我这样的
	path.pop_back();//回溯过程
}

完整代码:

class Solution {
public:
    vector<vector<int>> res;
    void backtracking(vector<int> path,int k,int sum,int n,int index)
    {
        if(sum>n)
            return ;
        if(path.size()==k)
        {
            if(sum==n)
                res.push_back(path);
            return;
        }
        for(int i=index;i<=9-(k-path.size())+1;i++)
        {
            path.push_back(i);
            backtracking(path,k,sum+i,n,i+1);
            path.pop_back();
        }
    }
    vector<vector<int>> combinationSum3(int k, int n) {
        vector<int> path;
        backtracking(path,k,0,n,1);
        return res;
    }
};

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

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

相关文章

01 从0开始搭建django环境

1 安装相关版本的django&#xff0c;这里&#xff0c;我以5.1.1为例子 pip3 install django5.1.1 (.venv) D:\DjangoCode\MS>pip3 install django5.1.1 Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple Collecting django5.1.1Using cached https://pypi.t…

算法题总结(七)——栈与队列

1、栈常用操作 &#xff08;1&#xff09;栈定义 Stack<Integer> stack new Stack<Integer>();&#xff08;2&#xff09;栈操作 .栈是否为空 isEmpty(); .查询栈顶元素&#xff0c;不改变栈 peek(); .弹出栈顶元素&#xff0c;改变栈 pop(); .压入栈顶 push(); …

Quantify LLM

大模型如果用bfloat16需要特别大的显存&#xff0c;所以都在用INT4、INT8做量化&#xff0c;效果不错 量化学习 为什么量化 对Llama13B模型来说&#xff0c;不同算子加载需要的显存不同 中间是TensorCore&#xff0c;左右两边是显存&#xff0c;加载过程中模型要频繁地将wei…

【移动端】事件基础

一、移动端事件分类 移动端事件主要分为以下几类&#xff1a; 1. 触摸事件&#xff08;Touch Events&#xff09; 触摸事件是移动设备特有的事件&#xff0c;用来处理用户通过触摸屏幕进行的操作。主要的触摸事件有&#xff1a; touchstart&#xff1a;手指触摸屏幕时触发。…

k8s 之动态创建pv失败(踩坑)

作者&#xff1a;程序那点事儿 日期&#xff1a;2024/02/05 18:53 初学容易范的错&#xff01; 问题简述&#xff1a; StorageClass创建成功&#xff0c;StatefulSet 启动不成功&#xff0c;与pvc关联的po和pvc一直是pending状态。 也就是说&#xff0c;StorageClass没有动态…

MQTT--Java整合EMQX

目录 1、简介2、准备3、使用步骤3.1 引入依赖3.2 创建生产者和消费者3.3 测试 总结PS: 1、简介 本文章实现了一个简单的MQTT客户端&#xff0c;使用Eclipse Paho库让Java和EMQX整合&#xff0c;测试客户端初始化时配置Broker地址、客户端ID、用户名和密码。连接成功后&#xf…

python sqlite3 工具函数

起因&#xff0c; 目的: sqlite3 最常用的函数。 比如&#xff0c;某人给了一个 database.db 文件。 但是你登录的时候&#xff0c;不知道账号密码。 此文件就是&#xff0c;查看这个数据库的详细内容。 有哪些表某个表的全部内容。添加数据 代码&#xff0c; 见注释 impor…

字节跳动收购Oladance耳机:强化音频技术,加速VR/AR生态布局

字节跳动收购Oladance耳机&#xff1a;加码VR/AR领域布局 近日&#xff0c;字节跳动宣布已完成对开放式耳机品牌Oladance的收购&#xff0c;实现了对该品牌的100%控股。这一收购标志着字节跳动在AI硬件领域的进一步扩展和深化&#xff0c;特别是对其VR/AR领域布局的重要加码。 …

python之运算符

1、算术运算符 算术运算符常用的有&#xff1a;&#xff0c;-&#xff0c;*&#xff0c; &#xff0c;/&#xff0c;//&#xff0c;%&#xff0c;>>,<< 1.1、加 常见的是算术相加&#xff0c;还有一种是字符串拼接。 a 10 b 20 print(a b) c "My &quo…

css 简单网页布局——浮动(一)

1. 三种布局方式 1.1 标准流 1.2 浮动的使用 1.3 简述浮动 1.3.1 浮动三大特性 <style>.out {border: 1px red solid;width: 1000px;height: 500px;}.one {background-color: aquamarine;width: 200px;height: 100px;}.two {background-color: blueviolet;width: 200px;h…

如何在算家云搭建CosyVoice(文生音频)

一、CosyVoice简介 CosyVoice 是一个开源的超强 TTS&#xff08;‌文本转语音&#xff09;‌模型&#xff0c;‌它支持多种生成模式&#xff0c;‌具有极强的语音自然可控性。‌ 具有以下特点&#xff1a; 语音合成 &#xff1a;能够将文本转换为自然流畅的语音输出。多语种…

让你的Github Profile高大时尚!

目录 前言 正文 GitHub Profile 特点&#xff1a; GitHub Actions 核心概念&#xff1a; 应用场景&#xff1a; RSS RSS的主要特点&#xff1a; 使用场景&#xff1a; RSS的工作原理&#xff1a; 关于Github Readme Card 关于Github贡献的3D图 关于个人最新博文的获取 关于代码…

今日指数-day08实战完整代码

今日指数-day08 1. 个股最新分时行情数据 1.1 个股最新分时行情功能说明 1&#xff09;个股最新分时行情功能原型 2&#xff09;个股最新分时行情数据接口分析 功能描述&#xff1a;获取个股最新分时行情数据&#xff0c;主要包含&#xff1a;开盘价、前收盘价、最新价、最…

(作业)第三期书生·浦语大模型实战营(十一卷王场)–书生基础岛第4关---InternLM + LlamaIndex RAG 实践

基础任务 (完成此任务即完成闯关) 任务要求&#xff1a;基于 LlamaIndex 构建自己的 RAG 知识库&#xff0c;寻找一个问题 A 在使用 LlamaIndex 之前InternLM2-Chat-1.8B模型不会回答&#xff0c;借助 LlamaIndex 后 InternLM2-Chat-1.8B 模型具备回答 A 的能力&#xff0c;截…

【MaskGAN】MaskGAN: Towards Diverse and Interactive Facial Image Manipulation

文章目录 MaskGAN: Towards Diverse and Interactive Facial Image Manipulationkey points贡献方法密集映射网络DMN编辑行为模拟训练多目标学习CelebAMask-HQ数据集实验消融实验总结MaskGAN: Towards Diverse and Interactive Facial Image Manipulation 会议/期刊:CVPR 202…

磁盘存储链式结构——B树与B+树

红黑树处理数据都是在内存中&#xff0c;考虑的都是内存中的运算时间复杂度。如果我们要操作的数据集非常大&#xff0c;大到内存已经没办法处理了该怎么办呢&#xff1f; 试想一下&#xff0c;为了要在一个拥有几十万个文件的磁盘中查找一个文本文件&#xff0c;设计的…

测试-BUG篇

文章目录 软件测试的生命周期BUGbug的概念描述bug的要素bug级别bug的生命周期 与开发产生争执怎么办&#xff08;高频考题&#xff09; 软件测试的生命周期 软件测试贯穿于软件的整个生命周期 BUG bug的概念 是指计算机程序中存在的一个错误(error)、缺陷(flaw)、疏忽(mista…

容器领航者:Kubernetes集群部署秘籍

目录 前言 一、ubernetes简介 1.1 应用部署方式演变 1.2 容器编排应用 1.3 kubenetes简介 二、Kubernetes核心概念 2.1 K8S各个组件用途 2.2 K8S 各组件之间的调用关系 2.3 K8S 的常用名词感念 2.4 k8S的分层架构​编辑 三、部署前的准备 3.1 k8s中容器的管理方式 3…

自然种子启发,4D 打印软机器人,环境探索新工具

想象一下&#xff0c;一颗小小的种子&#xff0c;竟能成为软机器人的灵感源泉&#xff01;在科技的奇妙世界里&#xff0c;受牻牛儿苗科种子启发&#xff0c;研究人员利用 4D 打印技术&#xff0c;打造出了具有独特性能的软机器人——《4D Printing of Humidity‐Driven Seed I…

免费!推荐10个可商用模特图片素材网站!

平时我也会用到一些可商用的模特图片素材&#xff0c;包括正版商用和免费商用的都有&#xff0c;接下来罗列国内外10个主流图片下载站点&#xff0c;保证你可以快速得到你想要的正版模特素材&#xff01; 1.包图网 传送门&#xff1a;https://ibaotu.com/sy 国内的一个高清分…