LeetCode题解 回溯(一):77 组合;216 组合总和III

news2024/11/26 12:52:44

回溯

从今天开始进入回溯,其实此前也接触过几道使用了该思想的题目

回溯的思想是“倒退到上一个状态”,通常结合递归,解决的问题多是“从众多组合中找出符合条件的组合”的问题,随想录中给出了题目大纲:

回溯算法大纲

回溯算法解决的问题可以抽象为树形结构,深度和广度决定了回溯算法遍历的次数,也可以近似递归,分为“函数返回类型 + 传入参数”、“终止条件”、“单层递归逻辑”三步。


77 组合 medium

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

只看题目,我们首先能想到的方法应该是暴力搜索,执行k个循环,但是暴力搜索带来的问题就是随着k的增大,时间复杂度会极高。

于是,为了以空间换时间,我们定义两个数组,一个用于存放所有组合,为我们最终的返回结果;另一个则用于记录k个数。

另外,为了避免已经遍历过的数不被重复遍历,我们需要一个参数,来限制每次回溯过程中的起始位置;

回溯结束的条件是数组中已经有了k个数;

每次回溯前,把当前结点添加入组成k个数的数组中,回溯后,再把当前结点删除,整体代码如下:

vector<vector<int>> res;
vector<int> path;

void reback (int n, int k, int startIndex) {
    if (path.size() == k) {
        res.push_back(path);
        return;
    }

    for (int i = startIndex; i <= n; ++i) {
        path.push_back(i);
        reback(n, k, i + 1);
        path.pop_back();
    }

    return;
}


vector<vector<int>> combine(int n, int k) {
    if (n == 0 || k == 0)   return {};
    reback(n, k, 1);
    return res;
}

这道题还有可以优化的空间。因为如果剩余的数字,不够组合成k个数字,那就没必要再遍历了。随想录中给出了一个极端的例子,n = 4, k = 4,只需要遍历一次就可以了,没必要让 i 从1一直增加到4;

再举个例子,就是n = 4, k = 3,当 i = 2时,算上2只剩下234三个数字,所有组合就已经可以遍历完了。根据当前回溯的起始位置startIndex和遍历总数n,来进行剪枝

  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。

所以,给出优化版本,代码如下:

vector<vector<int>> res;
vector<int> path;

void reback (int n, int k, int startIndex) {
    if (path.size() == k) {
        res.push_back(path);
        return;
    }

    for (int i = startIndex; i <= n - (k - path.size()) + 1; ++i) {
        path.push_back(i);
        reback(n, k, i + 1);
        path.pop_back();
    }

    return;
}


vector<vector<int>> combine(int n, int k) {
    if (n == 0 || k == 0)   return {};
    reback(n, k, 1);
    return res;
}

216 组合总和III medium

找出所有相加之和为 n 的 k 个数的组合,且满足下列条件:

  • 只使用数字1到9

  • 每个数字 最多使用一次

返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。

这道题相比较于上一道题,区别在于求和,只需要在传入参数中添加当前和,并在终止条件中判断,当前和是否等于目标和,而且候选数组大小等于k。

本题代码如下:

vector<vector<int>> res;
vector<int> path;

void reback (int k, int n, int startIndex, int sum) {
    if (sum == n && path.size() == k) {
        res.push_back(path);
        return;
    }

    for (int i = startIndex; i <= 9; ++i) {
        path.push_back(i);
        reback(k, n, i + 1, sum + i);
        path.pop_back();
    }
    return;
}

vector<vector<int>> combinationSum3(int k, int n) {
    reback(k, n, 1, 0);

    return res;
}

这道题也可以进行剪枝,剪枝操作根据当前的起始点和与目标值的差值来判断,即:

如果当前元素总和已经大于目标值了,就没必要往下遍历了

在终止条件前,加一个判断语句就可以了,代码如下:

vector<vector<int>> res;
vector<int> path;

void reback (int k, int n, int startIndex, int sum) {
    if (sum > n) return;
    if (sum == n && path.size() == k) {
        res.push_back(path);
        return;
    }

    for (int i = startIndex; i <= 9; ++i) {
        path.push_back(i);
        reback(k, n, i + 1, sum + i);
        path.pop_back();
    }
    return;
}

vector<vector<int>> combinationSum3(int k, int n) {
    reback(k, n, 1, 0);

    return res;
}

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

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

相关文章

Linux学习笔记——ZooKeeper集群安装部署

5.8、ZooKeeper集群安装部署 5.8.1、简介 Zookeeper是一个分布式的、开放源码的分布式应用程序协调服务&#xff0c;是Hadoop和HBase的重要组件。它是一个为分布式应用提供一致性服务的软件&#xff0c;提供的功能包括&#xff1a;配置维护、域名服务、分布式同步、组服务等。…

CHAPTER 2 Docker镜像

docker镜像2.1 docker image 获取2.1.1 命令格式&#xff08;pull&#xff09;2.1.2 层(layer)2.1.3 镜像重名2.2 查看镜像信息&#xff08;ls&#xff0c;tag&#xff0c;inspect&#xff0c;history&#xff09;2.2.1 使用images命令列出镜像&#xff08;ls&#xff09;2.2.2…

uni-app:小程序开发总结

内容持续更新中~~~&#x1f618;uniapp项目起步:工具下载在Dcloud 官网上下载 HBuilderX 开发工具,以及微信开发者工具.(同时你要在微信开发者文档进行小程序注册,拿到 ID, HBuilderX 和 微信开发者工具 你都要进行注册登录)项目创建我们可以通过HBuilderX 来进行基础版的项目创…

【阶段三】Python机器学习12篇:机器学习项目实战:朴素贝叶斯模型的算法原理与朴素贝叶斯分类模型

本篇的思维导图: 朴素贝叶斯模型的算法原理 朴素贝叶斯是贝叶斯模型当中最简单的一种,其算法核心为如下所示的贝叶斯公式: 其中P(A)为事件A发生的概率,P(B)为事件B发生的概率,P(A|B)表示在事件B发生的条件下事件A发生的概率,同理P(B|A)则表示在事件A发…

2023-01-10 clickhouse-聚合函数的源码再梳理

https://cloud.tencent.com/developer/article/1815441 1.IAggregateFunction接口梳理 话不多说&#xff0c;直接上代码&#xff0c;笔者这里会将所有聚合函数的核心接口代码全部列出&#xff0c;一一梳理各个部分&#xff1a; 构造函数 IAggregateFunction(const DataTypes …

Android设置本地字体文件ttf

目录 前言 ①使用typeface 方式 一、创建加载字体实例 二、使用步骤 1.在Application中加载字体 2.在xml中使用 ②使用fontFamily 方式 1、在res/font下导入ttf文件 2、在xml中使用 总结 前言 产品告诉UI设计设计图时要使用炫酷字体。因为Android不像网页项目可以使用…

如何使用Jasper导出用户列表数据?

场景说明在使用JasperjaspersoftStudio导出用户列表数据导出(如下图)是比较简单的&#xff0c;就是把用户列表数据&#xff0c;一个List集合放到 JRBeanCollectionDataSource中即可。但是如果有多个List集合需要导出呢&#xff0c;这个应该怎么办?比如&#xff1a;一个用户的集…

用Python发邮件(附完整源代码)

目录 一、背景 1.1、前言 1.2、说明 二、SMTP协议 2.1、SMTP协议作用 2.2、SSL作用 三、步骤 3.1、开启QQ邮箱SMTP 四、代码 4.1、完整源代码 五、结果 5.1、代码运行结果 六、总结 6.1、总结 一、背景 1.1、前言 写了一个简陋的2023年12306自动化购票程序&…

微服务保护 - Sentinel

1.概念&#xff1a; 一&#xff1a;sentinel 介绍 随着微服务的流行&#xff0c;服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式服务架构的轻量级流量控制产品&#xff0c;主要以流量为切入点&#xff0c;从流量控制、熔断降级、系统负载保护等多个维度来帮助…

黑马学ElasticSearch(六)

目录&#xff1a; &#xff08;1&#xff09;搜索结果处理-排序 &#xff08;2&#xff09;搜索结果处理-分页 &#xff08;3&#xff09;搜索结果处理-高亮 &#xff08;1&#xff09;搜索结果处理-排序 评分降序、价格升序查询 第二 第三 一旦进行了排序_score就没有值了 …

Qt 自定义流程图 diagram

Qt 自定义流程图 diagram前言程序执行效果程序源码下载图形视图框架成员介绍重写QGraphicsItem程序源码介绍重点代码前言 本文将对QGraphicsScene, QGraphicsView,QGraphicsItem这三个类进行简单介绍&#xff0c;并通过diagram流程图项目对自定义QGraphicsItem操作进行演示讲解…

Docker从无到有

随着各个软件的版本越来越多&#xff0c;软件开发、使用环境愈发复杂&#xff0c;Docker日益受到广泛应用。本文记录下从零开始了解、使用docker的各个步骤。 Docker有3个基本概念: Image&#xff0c;镜像。镜像就是系统的快照。静态。每个Image以<Repo Name>:<Tag …

求助:程序员得了结膜炎+干眼症怎么办?

大概是2022年12月初开始&#xff0c;我就感觉眼睛有看东西有点肿胀和模糊&#xff0c;还有就是总想眯眼。本来以为就是用眼过度导致的疲劳&#xff0c;想着周六周日好好休息一下应该就好了&#xff0c;但是没想到不仅没好还加重了。不得已去了医院求助医生。 我去的是杭州的浙…

TS:镜像构建过程中go下载第三方包失败-2023.1.8(已解决)

title: TS&#xff1a;镜像构建过程中go下载第三方包失败-2023.1.8(已解决) date: 2023-1-10 categories: Golang tags:Golang TS&#xff1a;镜像构建过程中go下载第三方包失败-2023.1.8(已解决) 注意&#xff1a;一定要注意项目代码里go版本和自己机器go版本是否一致&#x…

5.2中断系统中的设备树——Linux对中断处理的框架及代码流程简述

当发生中断时&#xff0c;CPU会跳到一个固定的地址去执行代码&#xff0c;这个固定的地址就被称为中断向量。 以ARM920T为例&#xff0c;它的中断向量默认是地址24&#xff08;0x18&#xff09;的地方。那么&#xff0c;就可以在这里放一条跳转指令。 一系列的跳转指令用来处…

基于配置系统和流水线的热更新方案

文章目录背景方案调研具体方案方案优缺点背景 最近我们要在一个新的 App 上增加热更新的能力&#xff0c;按照以往的设计思路&#xff0c;需要后台一起参与&#xff0c;并提供对应的接口&#xff0c;具体的接口如下&#xff1a; 接口参数返回值备注uploadBasePkgappVersion&a…

接口管理工具YApi怎么用?颜值高、易管理、超好用

众多接口管理工具如雨后春笋搬冒出。让人欣慰的是&#xff0c;有许多优秀作品来自国内&#xff0c;包含YApi和rap。看着中文的官网&#xff0c;熟悉的汉语&#xff0c;不禁让人暗爽。当然这也就带来另一个弊端&#xff0c;因为使用基数少&#xff0c;所以参考资料少。我们想学习…

Linux时间的获取与使用

Linux系统时间有两种。 &#xff08;1&#xff09;日历时间。该值是自协调世界时(UTC)1970年1月1日00:00:00这个特定时间以来所经过的秒数累计值。基本数据类型用time_t保存。最后通过转换才能得到我们平时所看到的24小时制或者12小时间制的时间。 &#xff08;2&#xff09;…

使用WSL获得Ubuntu系统环境

文章目录使用WSL获得Ubuntu系统环境为什么要用WSL什么是WSLWSL部署安装Windows Terminal软件使用WSL获得Ubuntu系统环境 为什么要用WSL WSL作为Windows10系统带来的全新特性&#xff0c;正在逐步颠覆开发人员既有的选择。 传统方式获取Linux操作系统环境&#xff0c;是安装完…

凯撒加密Caesar cipher

凯撒加密的由来凯撒加密正是凯撒大帝发明的&#xff0c;是一种古典的加密凯撒率军征服高卢&#xff0c;袭击日耳曼和不列颠&#xff0c;古罗马开启了走出意大利&#xff0c;征服全欧洲的征程仅用8年时间征服高卢后&#xff0c;凯撒率军越过卢比孔河&#xff0c;驱赶政敌&#x…