算法练习-组合【回溯算法】(思路+流程图+代码)

news2024/12/28 3:35:57

难度参考

        难度:困难

        分类:回溯算法

        难度与分类由我所参与的培训课程提供,但需 要注意的是,难度与分类仅供参考。且所在课程未提供测试平台,故实现代码主要为自行测试的那种,以下内容均为个人笔记,旨在督促自己认真学习。

题目

        给定两个整数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]]

        提示:<=n<=201<=k<=n

思路

        1. 初始化:首先,我们需要一个结果集合来存储所有符合条件的组合,以及一个临时数组(或者称之为路径)来存储当前探索的组合。

        2. 递归与回溯:我们从1开始遍历到n,尝试将每个数加入到当前的组合中,并递归地继续这个过程,直到当前组合的长度等于k,表示我们找到了一个有效的组合,将其添加到结果集中。每次递归调用后,我们需要回溯,即移除当前组合的最后一个元素,以尝试下一个可能的数字。

        3. 终止条件:当当前组合的长度等于k时,将其加入到结果集中,并返回上一层递归。

        具体来说就是,

        1. 定义辅助函数:定义一个辅助函数`combineHelper`,它接受当前数字`start`、当前路径`path`和结果集`result`作为参数。这个函数将负责递归地构建组合。

        2. 递归构建组合:从`start`开始,遍历到n,对于每个数`i`,将其加入到`path`中,然后递归地调用`combineHelper`,将`i+1`作为新的起始点,因为组合是不考虑顺序的,所以我们不需要重复包含之前的数字。

        3. 回溯:在每次递归调用返回后,我们需要从`path`中移除最后加入的数字,这样我们就可以尝试下一个数字。

        4. 收集结果:每当`path`的长度等于k时,就将其复制到结果集中,因为我们找到了一个有效的组合。

示例

        当然,让我们通过一个具体的例子来详细解释这个过程。假设我们有n = 4和k = 2,我们的目标是找到从1到4的所有可能的2个数的组合。

        初始状态

        - 结果集(用于存储所有组合):[]
        - 当前路径(当前探索的组合):[]
        - 开始数字:1

        第一层递归

        我们从数字1开始探索。

        - 当前路径:[1]

        接下来,我们进入下一层递归,尝试添加2、3、4到当前路径。

        第二层递归(以1开始)

        - 尝试添加2,当前路径变为[1, 2]。因为当前路径的长度等于k(2),我们找到了一个有效组合,将其添加到结果集中,然后回溯,移除2,当前路径回到[1]。
        - 接着尝试添加3,当前路径变为[1, 3]。同样,这是一个有效组合,添加到结果集,然后回溯,移除3,当前路径再次回到[1]。
        - 最后尝试添加4,当前路径变为[1, 4]。这也是一个有效组合,添加到结果集,然后回溯,移除4,当前路径回到[1]。

        此时,以1开头的所有可能组合都已探索完毕,我们移除1,回到初始状态,当前路径[],并尝试下一个数字。

        第一层递归(以2开始)

        - 当前路径:[2]

        重复之前的过程:

        - 尝试添加3,当前路径变为[2, 3]。这是一个有效组合,添加到结果集,然后回溯。
        - 尝试添加4,当前路径变为[2, 4]。这也是一个有效组合,添加到结果集,然后回溯。

        此时,以2开头的所有可能组合都已探索完毕,我们继续尝试以3和4开头的组合。

        结果

        按照这个过程,我们最终得到的结果集是:

        - [1, 2]
        - [1, 3]
        - [1, 4]
        - [2, 3]
        - [2, 4]
        - [3, 4]

        这就是所有从1到4中选2个数的组合。

        这个例子展示了回溯算法的工作原理:通过递归探索所有可能的路径,并在满足条件时收集结果,同时使用回溯来撤销最后的选择,从而尝试其他可能的选项。

梳理

        这种方法能够实现的原理基于回溯算法,这是一种通过递归来探索所有可能选择的算法框架,用于解决一类需要遍历所有可能情况来寻找所有解的问题。其核心思想和工作机制可以概括为以下几点:

        1. 选择与探索:从一系列的选项中逐一选择,然后向下探索,直到达到问题的底部(基本情况),这个过程类似于深度优先搜索(DFS)。

        2. 约束条件:在探索过程中,通过约束条件来剪枝,即提前排除那些明显不会得到解的路径。在组合问题中,约束条件可能是组合的长度达到了指定的值。

        3. 回溯:当达到基本情况或者当前路径不满足约束条件时,算法将回溯到上一个决策点,撤销最后的选择,并尝试其他可能的选项。这个过程保证了所有的可能性都被探索过。

        4. 记录解:每当找到一个满足条件的解时,就将其记录下来。在组合问题中,每当构建的组合长度达到指定的k时,就将其添加到结果集中。

        具体到组合问题(如从1到n的所有可能的k个数的组合),回溯算法的工作过程如下:

        - 从1开始,逐一尝试每个数作为组合的第一个数,然后递归地尝试所有可能的下一个数。
        - 在递归过程中,如果当前组合的长度达到了k,就将其记录为一个解。
        - 如果当前组合还没达到k,就继续添加下一个可能的数,直到无法再添加(因为已经达到n或者组合已满)。
        - 每当回溯到某个决策点时,尝试下一个数作为当前位置的数,直到所有数都尝试过。

        通过这种方式,回溯算法能够有效地遍历所有可能的组合,确保找到所有满足条件的解。这种方法之所以有效,是因为它通过递归和回溯机制,实现了对解空间的系统性搜索,同时通过约束条件和撤销选择(回溯)来减少不必要的搜索,从而提高效率。

代码


#include <iostream>  // 包含输入输出流库
#include <vector>     // 包含向量库
using namespace std;  // 使用标准命名空间

void combineHelper(int n, int k, int start, vector<int>& path, vector<vector<int>>& result) {
    // 当路径长度等于k时,将其加入结果集
    if (path.size() == k) {
        result.push_back(path);  // 将路径加入结果
        return;
    }
    
    // 从start开始遍历到n
    for (int i = start; i <= n; ++i) {
        // 将当前数字加入路径
        path.push_back(i);
        // 递归调用,注意下一次的起始数字是i+1,因为组合不考虑顺序
        combineHelper(n, k, i + 1, path, result);
        // 回溯,移除路径上的最后一个数字,尝试下一个可能的数字
        path.pop_back();
    }
}

vector<vector<int>> combine(int n, int k) {
    vector<vector<int>> result;  // 存储结果的二维向量
    vector<int> path;  // 存储当前路径的向量
    combineHelper(n, k, 1, path, result);  // 调用辅助函数组合路径
    return result;  // 返回全部结果
}

int main() {
    int n = 4, k = 2;  // 设定初始n和k
    vector<vector<int>> result = combine(n, k);  // 执行组合函数

    cout << "[";  // 输出左括号

    for (int i = 0; i < result.size(); ++i) {  // 遍历结果集
        cout << "[";  // 输出左括号
        for (int j = 0; j < result[i].size(); ++j) {  // 遍历每个组合
            cout << result[i][j];  // 输出当前数字
            if (j < result[i].size() - 1) cout << ",";  // 如果不是该组合的最后一个数字,输出逗号
        }
        cout << "]";  // 输出右括号
        if (i < result.size() - 1) cout << ",";  // 如果不是最后一个组合,输出逗号
    }

    cout << "]" << endl;  // 输出右括号并换行

    // 示例2
    n = 1; k = 1;  // 设定新的n和k
    result = combine(n, k);  // 执行组合函数

    cout << "[";  // 输出左括号

    for (int i = 0; i < result.size(); ++i) {  // 遍历结果集
        cout << "[";  // 输出左括号
        for (int j = 0; j < result[i].size(); ++j) {  // 遍历每个组合
            cout << result[i][j];  // 输出当前数字
            if (j < result[i].size() - 1) cout << ",";  // 如果不是该组合的最后一个数字,输出逗号
        }
        cout << "]";  // 输出右括号
        if (i < result.size() - 1) cout << ",";  // 如果不是最后一个组合,输出逗号
    }

    cout << "]" << endl;  // 输出右括号并换行

    return 0;  // 程序正常结束
}

        时间复杂度:0(n*2^n)

        空间复杂度:0(n)

打卡

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

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

相关文章

Code-Audit(代码审计)习题记录6-7

介绍&#xff1a; 自己懒得搭建靶场了&#xff0c;靶场地址是 GitHub - CHYbeta/Code-Audit-Challenges: Code-Audit-Challenges为了方便在公网练习&#xff0c;可以随地访问&#xff0c;本文所有的题目均来源于网站HSCSEC-Code Audit 6、习题6 题目内容如下&#xff1a; 源代…

Python+Flask低代码数据融合引擎工具

我用了2年多时间开发了一个低代码数据融合引擎工具 1.整体界面 2.主要功能 1)通过excel文件生成mysql数据表结构及数据保存 说明:功能细节包括(excel文件上传,文件内容预览,建表导入数据),难点在于对excel数据类型判断,并与mysql数据类型对应 2)建立数据表结构并批量导入数据 …

python程序设计基础:字符串与正则表达式

第四章&#xff1a;字符串与正则表达式 4.1字符串 最早的字符串编码是美国标准信息交换码ASCII&#xff0c;仅对10个数字、26个大写英文字母、26个小写英文字母及一些其他符号进行了编码。ASCII码采用1个字节来对字符进行编码&#xff0c;最多只能表示256个符号。 随着信息技…

Ubuntu20.04开启/禁用ipv6

文章目录 Ubuntu20.04开启/禁用ipv61.ipv62. 开启ipv6step1. 编辑sysctl.confstep2. 编辑网络接口配置文件 3. 禁用ipv6&#xff08;sysctl&#xff09;4. 禁用ipv6&#xff08;grub&#xff09;附&#xff1a;总结linux网络配置 Ubuntu20.04开启/禁用ipv6 1.ipv6 IP 是互联网…

openssl

最新版本3.0 使用 生成自签名的根证书 openssl req -x509 -new -key rootCA.key -days 3650 -out rootCA.crt -subj "/CCA/STCA/LCA/OCA/OUCA/CNCA" pem格式 BASE64&#xff0c;会有PUBLIC KEY表示公钥&#xff0c;PRIVATE KEY表示私钥 根据私钥生成公钥 openss…

工业信息安全的神秘武器——德迅卫士(主机安全)

前言&#xff1a; 服务器作为承载公司业务及内部运转的底层平台&#xff0c;其稳定、安全地运行是公司的正常发展的前提保障。由于主机上运行着各种各样的业务&#xff0c;会存在着各类漏洞及安全问题。攻击者以此为目标&#xff0c;通过对服务器的攻击来获利&#xff0c;给公司…

英文输入法(C 语言)

题目来自于博主算法大师的专栏&#xff1a;最新华为OD机试C卷AB卷OJ&#xff08;CJavaJSPy&#xff09; https://blog.csdn.net/banxia_frontend/category_12225173.html 题目 主管期望你来实现英文输入法单词联想功能&#xff0c;需求如下&#xff1a; 依据用户输入的单词前…

Java智慧工地云综合管理平台SaaS源码 助力工地实现精细化管理

目录 智慧工地系统介绍 1、可视化大屏 2、视频监控 3、Wi-Fi安全教育 4、环境监测 5、高支模监测 6、深基坑监测 7、智能水电监测 8、塔机升降安全监测 智慧工地系统功能模块 1、基础数据管理 2、考勤管理 3、安全隐患管理 4、视频监控 5、塔吊监控 6、升降机监…

三分钟快速搭建家纺行业小程序商城:轻松实现电子商务梦想

随着互联网的普及和移动设备的广泛使用&#xff0c;越来越多的商业活动正在向数字化转型。在这个过程中&#xff0c;小程序商城作为一种新型的电子商务模式&#xff0c;正逐渐受到商家的青睐。本文将通过具体步骤&#xff0c;指导读者如何开发一个纺织辅料小程序商城。 一、选择…

Capto 一款适用Mac屏幕录制编辑软件

Capto 是一款功能强大的 Mac 屏幕录制和编辑软件&#xff0c;能够满足用户的多种录制和编辑需求。无论是个人还是专业用户&#xff0c;都可以通过 Capto 实现高质量的屏幕录制和编辑。 首先&#xff0c;Capto 提供了全面的屏幕录制功能&#xff0c;包括全屏、选中区域、甚至是摄…

Nest.js权限管理系统开发(三)环境变量与配置文件

一般来说数据库的配置包含了一些敏感信息&#xff0c;不宜写在代码中提交到远程仓库&#xff0c;所以我们可以将配置写在配置文件中,然后提交 git 时候将生产环境的配置文件其忽略。我们可以新建.env和.env.prod两个文件分别存放开发与生产环境配置&#xff0c;也可以使用YAML等…

Linux【动静态库】

目录 1.软硬链接 1.1软硬链接的语法 1.2理解软硬链接 1.3目录文件的硬链接 1.4应用场景 1.5ACM时间 2.动静态库 2.1认识库 3.制作静态库 3.1静态库打包 3.2静态库的使用 4.制作动态库 4.1动态库打包 4.2动态库的链接使用 4.3动态库的链接原理 总结&#xff1…

[晓理紫]每日论文分享(有中文摘要,源码或项目地址)--强化学习等

专属领域论文订阅 关注{晓理紫|小李子}&#xff0c;每日更新论文&#xff0c;如感兴趣&#xff0c;请转发给有需要的同学&#xff0c;谢谢支持 如果你感觉对你有所帮助&#xff0c;请关注我&#xff0c;每日准时为你推送最新论文。 分类: 大语言模型LLM视觉模型VLM扩散模型视觉…

Kotlin 基本语法5 继承,接口,枚举,密封

1.继承与重写的Open关键字 open class Product(val name:String ) {fun description() "Product: $name"open fun load() "Nothing .."}class LuxuryProduct:Product("Luxury"){//继承需要调用 父类的主构造函数override fun load(): String {…

热点参数流控(Sentinel)

热点参数流控 热点流控 资源必须使用注解 @SentinelResource编写接口 以及 热点参数流控处理器 /*** 热点流控 必须使用注解 @SentinelResource* @param id* @return*/ @RequestMapping("/getById/{id}") @SentinelResource(value = "getById", blockHand…

《Docker 简易速速上手小册》第3章 Dockerfile 与镜像构建(2024 最新版)

文章目录 3.1 编写 Dockerfile3.1.1 重点基础知识3.1.2 重点案例&#xff1a;创建简单 Python 应用的 Docker 镜像3.1.3 拓展案例 1&#xff1a;Dockerfile 优化3.1.4 拓展案例 2&#xff1a;多阶段构建 3.2 构建流程深入解析3.2.1 重点基础知识3.2.2 重点案例&#xff1a;构建…

外星文明会是朋友还是敌人?科学家用AI模拟揭示惊人答案!

引言&#xff1a;人类与外星文明的潜在互动 自古以来&#xff0c;人类就对外太空充满了好奇与向往&#xff0c;无数科幻作品中都描绘了人类与外星文明的潜在互动。然而&#xff0c;这些互动并非总是和平友好的&#xff0c;正如物理学家Stephen Hawking所警告的&#xff0c;盲目…

2024年全国乙卷高考文科数学备考:历年选择题真题练一练(2014~2023)

今天距离2024年高考还有三个多月的时间&#xff0c;今天我们来看一下2014~2023年全国乙卷高考文科数学的选择题&#xff0c;从过去十年的真题中随机抽取5道题&#xff0c;并且提供解析。后附六分成长独家制作的在线练习集&#xff0c;科学、高效地反复刷这些真题&#xff0c;吃…

小苯的IDE括号问题(CD) -----牛客小白月赛87(双链表)

C题&#xff1a;C-小苯的IDE括号问题&#xff08;easy&#xff09;_牛客小白月赛87 (nowcoder.com) D题&#xff1a; D-小苯的IDE括号问题&#xff08;hard&#xff09;_牛客小白月赛87 (nowcoder.com) C题代码&#xff1a; #include<bits/stdc.h>using namespace std…

HTTP攻击,该怎么防护

一般网络世界里为人们所熟知的DDoS攻击&#xff0c;多数是通过对带宽或网络计算资源的持续、大量消耗&#xff0c;最终导致目标网络与业务的瘫痪&#xff1b;这类DDOS攻击&#xff0c;工作在OSI模型的网络层与传输层&#xff0c;利用协议特点构造恶意的请求载荷来达成目标资源耗…