代码随想录算法训练营第二十三天|Day23 回溯算法

news2024/10/22 23:40:52

39. 组合总和

题目链接/文章讲解:https://programmercarl.com/0039.%E7%BB%84%E5%90%88%E6%80%BB%E5%92%8C.html

视频讲解:https://www.bilibili.com/video/BV1KT4y1M7HJ

思路

int* path;
int pathTop;
int** ans;
int ansTop;
int* length;
void backTracking(int target, int index, int* candidates, int candidatesSize, int sum) {
    if(sum >= target) {
        if(sum == target) {
            int* tempPath = (int*)malloc(sizeof(int) * pathTop);
            int j;
            for(j = 0; j < pathTop; j++) {
                tempPath[j] = path[j];
            }
            ans[ansTop] = tempPath;
            length[ansTop++] = pathTop;
        }
        return ;
    }
    int i;
    for(i = index; i < candidatesSize; i++) {
        sum+=candidates[i];
        path[pathTop++] = candidates[i];
        backTracking(target, i, candidates, candidatesSize, sum);
        sum-=candidates[i];
        pathTop--;
    }
}

int** combinationSum(int* candidates, int candidatesSize, int target, int* returnSize, int** returnColumnSizes){
    path = (int*)malloc(sizeof(int) * 50);
    ans = (int**)malloc(sizeof(int*) * 200);
    length = (int*)malloc(sizeof(int) * 200);
    ansTop = pathTop = 0;
    backTracking(target, 0, candidates, candidatesSize, 0);
    *returnSize = ansTop;
    *returnColumnSizes = (int*)malloc(sizeof(int) * ansTop);
    int i;
    for(i = 0; i < ansTop; i++) {
        (*returnColumnSizes)[i] = length[i];
    }
    return ans;
}

学习反思

代码定义了几个全局变量:

  • "path"是一个数组,用于存储当前正在探索的数字组合。
  • "pathTop"是"path"数组中下一个可用位置的索引。
  • "ans"是一个二维数组,用于存储所有有效的数字组合。
  • "ansTop"是"ans"数组中下一个可用位置的索引。
  • "length"是一个数组,用于存储"ans"数组中每个组合的长度。

"backTracking"函数是主要的递归函数,它探索所有可能的组合。它接收目标值、当前候选数数组的索引、候选数数组、候选数数组的大小和当前数字组合的和作为参数。

该函数首先检查当前和是否大于或等于目标值。如果是,它再检查和是否等于目标值。如果是,它创建一个名为"tempPath"的新数组,并将当前组合从"path"数组复制到它。然后,它将"tempPath"数组添加到"ans"数组中,并将组合的长度存储在"length"数组中。最后,它递增"ansTop"变量。然后,该函数继续探索候选数数组中的下一个数字。它通过从当前索引迭代到候选数数组的末尾来实现。对于每个数字,它将其添加到和中,将其添加到"path"数组中,并使用更新后的参数递归调用"backTracking"函数。在递归调用之后,它更新和路径变量以移除添加的数字,实际上回溯到先前的状态。最后,"combinationSum"函数初始化全局变量,调用"backTracking"函数,并设置返回数组的大小和列大小。

40.组合总和II

题目链接/文章讲解:https://programmercarl.com/0040.%E7%BB%84%E5%90%88%E6%80%BB%E5%92%8CII.html

视频讲解:https://www.bilibili.com/video/BV12V4y1V73A

思路

int* path;
int pathTop;
int** ans;
int ansTop;
int* length;
int cmp(const void* a1, const void* a2) {
    return *((int*)a1) - *((int*)a2);
}
void backTracking(int* candidates, int candidatesSize,  int target, int sum, int startIndex) {
    if(sum >= target) {
        if(sum == target) {
            int* tempPath = (int*)malloc(sizeof(int) * pathTop);
            int j;
            for(j = 0; j < pathTop; j++) {
                tempPath[j] = path[j];
            }
            length[ansTop] = pathTop;
            ans[ansTop++] = tempPath;
        }
        return ;
    }
    int i;
    for(i = startIndex; i < candidatesSize; i++) {
        if(i > startIndex && candidates[i] == candidates[i-1])
            continue;
        path[pathTop++] = candidates[i];
        sum += candidates[i];
        backTracking(candidates, candidatesSize, target, sum, i + 1);
        sum -= candidates[i];
        pathTop--;
    }
}
int** combinationSum2(int* candidates, int candidatesSize, int target, int* returnSize, int** returnColumnSizes){
    path = (int*)malloc(sizeof(int) * 50);
    ans = (int**)malloc(sizeof(int*) * 100);
    length = (int*)malloc(sizeof(int) * 100);
    pathTop = ansTop = 0;
    qsort(candidates, candidatesSize, sizeof(int), cmp);
    backTracking(candidates, candidatesSize, target, 0, 0);
    *returnSize = ansTop;
    *returnColumnSizes = (int*)malloc(sizeof(int) * ansTop);
    int i;
    for(i = 0; i < ansTop; i++) {
        (*returnColumnSizes)[i] = length[i];
    }
    return ans;
}

学习反思

在回溯算法之前,对候选数数组进行了快速排序。通过将相同的元素放在一起,可以避免在搜索过程中出现重复的组合。这样做可以减少递归调用的次数,从而提高算法的效率。其次,在递归调用的过程中,添加了一个判断条件。当遍历到同一层级的相同元素时,跳过对其的处理。这样可以避免产生重复的组合,进一步提高算法的效率。此外,对动态分配的数组也进行了一些调整。在ans数组中,不再使用ansTop指针来记录数组元素的位置,而是直接将ans数组中的每个元素与length数组中的相应位置关联起来。这样可以更方便地管理组合的长度信息。

131.分割回文串

题目链接/文章讲解:

https://programmercarl.com/0131.%E5%88%86%E5%89%B2%E5%9B%9E%E6%96%87%E4%B8%B2.html

视频讲解:https://www.bilibili.com/video/BV1c54y1e7k6

思路

char** path;
int pathTop;
char*** ans;
int ansTop = 0;
int* ansSize;
void copy() {
    char** tempPath = (char**)malloc(sizeof(char*) * pathTop);
    int i;
    for(i = 0; i < pathTop; i++) {
        tempPath[i] = path[i];
    }
    ans[ansTop] = tempPath;
    ansSize[ansTop++] = pathTop;
}
bool isPalindrome(char* str, int startIndex, int endIndex) {
    while(endIndex >= startIndex) {
        if(str[endIndex--] != str[startIndex++])
            return 0;
    }
    return 1;
}
char* cutString(char* str, int startIndex, int endIndex) {
    char* tempString = (char*)malloc(sizeof(char) * (endIndex - startIndex + 2));
    int i;
    int index = 0;
    for(i = startIndex; i <= endIndex; i++)
        tempString[index++] = str[i];
    tempString[index] = '\0';
    return tempString;
}
void backTracking(char* str, int strLen,  int startIndex) {
    if(startIndex >= strLen) {
        copy();
        return ;
    }

    int i;
    for(i = startIndex; i < strLen; i++) {
        if(isPalindrome(str, startIndex, i)) {
            path[pathTop++] = cutString(str, startIndex, i);
        }
        else {
            continue;
        }
        backTracking(str, strLen, i + 1);
        pathTop--;
    }
}

char*** partition(char* s, int* returnSize, int** returnColumnSizes){
    int strLen = strlen(s);
    path = (char**)malloc(sizeof(char*) * strLen);
    ans = (char***)malloc(sizeof(char**) * 40000);
    ansSize = (int*)malloc(sizeof(int) * 40000);
    ansTop = pathTop = 0;
    backTracking(s, strLen, 0);
    *returnSize = ansTop;
    *returnColumnSizes = (int*)malloc(sizeof(int) * ansTop);
    int i;
    for(i = 0; i < ansTop; ++i) {
        (*returnColumnSizes)[i] = ansSize[i];
    }
    return ans;
}

学习反思

  1. 将输入的字符串转换为字符数组,以便于通过索引访问和取子串。
  2. 定义一个辅助函数isPalindrome,使用双指针法判断子串是否为回文字符串。
  3. 初始化结果数组result和切割方案数组path。
  4. 定义回溯函数backtracking,传入参数startIndex表示当前要切割的子串的起始索引。
  5. 终止条件为startIndex超过字符串长度,此时收集切割方案path并添加到结果数组result中。
  6. 遍历从startIndex到字符串末尾的所有子串,判断子串是否为回文字符串。如果是,将子串添加到切割方案path中,然后递归调用backtracking函数来寻找下一个起始位置的子串。
  7. 在递归调用之后,如果切割方案path非空,将最后一个元素弹出,进行回溯操作。
  8. 最后调用backtracking函数,startIndex初始为0,完成递归回溯的过程。
  9. 返回结果数组result。

在Swift中,使用数组来存储结果集和切割方案,通过append和removeLast方法来添加和移除元素。通过回溯算法,可以找到所有满足条件的切割方案。时间复杂度为O(N * 2^N)

总结

对回溯算法有了更深刻的认识,加油!!!

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

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

相关文章

【凸优化】Legendre变换、共轭函数、对偶

推荐文章 [凸优化-凸共轭]Legendre and Legendre-Fenchel transforms - 知乎 (zhihu.com) 一、Legendre变换 1、几何解释1 Legendre 变换通过选择斜率 作为新的自变量&#xff0c;将函数描述为它的斜率与相应的 x 的函数值之间的关系。几何上&#xff0c;它可以理解为用函…

Vert.x,认证与授权 - HTTP基本认证

几乎所有的线上系统都离不开认证和授权&#xff0c;Vert.x auth相关组件提供了丰富(Session&#xff0c;JTW, OAuth&#xff0c;…)&#xff0c;便捷的认证和授权支持。 当前&#xff0c;使用最多是Web应用&#xff0c;所以在后续讨论中&#xff0c;都是关于Vert.x auth在Web应…

kernel32.dll下载地址:如何安全地恢复系统文件

关于从网络上寻找kernel32.dll的下载地址&#xff0c;这通常不是一个安全的做法&#xff0c;而且可能涉及到多种风险。kernel32.dll是Windows操作系统的核心组件之一&#xff0c;负责内存管理、进程和线程管理以及其他关键系统功能。因为kernel32.dll是系统的基础文件&#xff…

IDEA如何给debug断点加上筛选条件判断

前言 我们在使用IDEA开发Java应用时&#xff0c;经常是需要进行代码调试的&#xff0c;这就需要打断点进行操作。但有些时候&#xff0c;我们只希望在符合某种条件的情况下&#xff0c;才去到这个断点&#xff0c;不符合的情况下&#xff0c;直接跳过断点&#xff0c;这其实也…

【linux】线程 (三)

13. 常见锁概念 &#xff08;一&#xff09;了解死锁 死锁是指在一组进程中的各个进程均占有不会释放的资源&#xff0c;但因互相申请被其他进程占有的&#xff0c;且不释放的资源&#xff0c;而处于的一种永久等待状态 &#xff08;二&#xff09;死锁四个必要条件 互斥条件…

深度学习(一)基础:神经网络、训练过程与激活函数(1/10)

深度学习基础&#xff1a;神经网络、训练过程与激活函数 引言&#xff1a; 深度学习作为机器学习的一个子领域&#xff0c;近年来在人工智能的发展中扮演了举足轻重的角色。它通过模仿人脑的神经网络结构&#xff0c;使得计算机能够从数据中学习复杂的模式和特征&#xff0c;…

COLA架构生成DDD项目

1.下载代码 https://github.com/alibaba/COLA 2.执行命令 2.1 shell Linux mvn archetype:generate \-DgroupIdcom.xxc \-DartifactIdcola-springboot-demo \-Dversion0.0.1 \-Dpackagecom.xxc.demo \-DarchetypeArtifactIdcola-framework-archetype-web \-DarchetypeGrou…

我是类(最终版)

文章目录 再看构造函数类型转换static静态成员友元内部类匿名对象对象拷贝时的编译器优化 再看构造函数 本标题的目的是解决如下问题&#xff1a;当实现MyQueue时&#xff0c;我们不需要写默认构造函数&#xff0c;因为编译器会调用Stack的默认构造&#xff0c;但是&#xff0…

01 设计模式-创造型模式-工厂模式

工厂模式&#xff08;Factory Pattern&#xff09;是 Java 中最常用的设计模式之一&#xff0c;它提供了一种创建对象的方式&#xff0c;使得创建对象的过程与使用对象的过程分离。 工厂模式提供了一种创建对象的方式&#xff0c;而无需指定要创建的具体类。 通过使用工厂模式…

vue 页面导出gif图片 img 导出gif 超简单~

1.首先需要新建一个文件件 新建gif文件夹。这两个文件在文章最后面需要可自提 2.出gif分为两种情况 第一种情况 页面是img标签&#xff0c;直接导出图片作为gif 第二种情况 页面是div标签&#xff0c;需要导出div里面的图片作为gif 2.1页面是img标签&#xff0c;直接导出图…

电脑异常情况总结

文章目录 笔记本无症状息屏黑屏 笔记本无症状息屏黑屏 &#x1f34e; 问题描述&#xff1a; 息屏导致黑屏&#xff1b;依次操作计算机--》右键--》管理--》事件查看器--》Windows日志--》系统&#xff1b;从息屏到异常黑屏之间出现了很多错误&#xff0c;如下&#xff1a;事件…

使用CMake生成动态链接库(.dll和.so)和静态链接库(.lib和.a)的方法

&#xff08;一&#xff09;简介 对于大型软件开发&#xff0c;动态连接库是必不可少的。不仅可以实现模块的封装&#xff0c;而且可以实现软件的热更新&#xff08;即替换windows下的.dll或Linux下的.so文件后直接实现软件更新&#xff0c;无需重新编译&#xff09;。有时也需…

力扣 困难 52.N皇后II

文章目录 题目介绍题解 题目介绍 题解 法一&#xff1a;返回51题N皇后List的长度 法二&#xff1a; class Solution {private int n, ans;private boolean[] onPath, diag1, diag2;public int totalNQueens(int n) {this.n n;onPath new boolean[n];diag1 new boolean[n * …

Standard IO

为了提高可移植性&#xff0c;将通用IO接口经过再封装就形成了标准IO&#xff0c;标准IO不仅适用于Unix环境&#xff0c;也兼容非Unix环境&#xff0c;这也是为什么说我们应该尽可能的使用标准IO&#xff0c;通用IO通过文件描述符fd来与文件交互&#xff0c;为了以示区分&#…

element plus e-table表格中使用多选,当翻页时已选中的数据丢失

摘要&#xff1a; 点击第一页选中两个&#xff0c;再选择第二页&#xff0c;选中&#xff0c;回到第一页&#xff0c;之前选中的要保留&#xff01; element ui table 解决办法&#xff1a; :row-key“getRowKeys” &#xff08;写在el-table中&#xff09; methods中声明 ge…

多一DY4100数字式接地电阻测试仪使用测量方法

接地电阻二线法测量步骤 1、找出一套简易测试线&#xff0c;一根红色两插头线和一根短绿线&#xff1b; 2、找出一根辅助地钉&#xff0c;距离被测接地桩/扁铁约五米远整根打下去&#xff1b; 3、绿线插头接仪器E孔&#xff08;绿色孔&#xff09;&#xff0c;夹子夹需测的接…

ArcGIS002:软件自定义设置

摘要&#xff1a;本文详细介绍安装arcgis10.2后软件自定义设置内容&#xff0c;包括工具条的启用、扩展模块的启用、如何加载项管理器、快捷键设置、样式管理器的使用以及软件常规设置。 一、工具条的启用 依次点击菜单栏【自定义】->【工具条】&#xff0c;根据工作需求勾…

医院信息化与智能化系统(5)

医院信息化与智能化系统(5) 这里只描述对应过程&#xff0c;和可能遇到的问题及解决办法以及对应的参考链接&#xff0c;并不会直接每一步详细配置 如果你想通过文字描述或代码画流程图&#xff0c;可以试试PlantUML&#xff0c;告诉GPT你的文件结构&#xff0c;让他给你对应的…

【漏洞修复/安全补丁】5.4之前版本通过api/products接口进行sql注入的问题

5.4之前版本&#xff0c;会使用api/products接口的selectId参数进行sql注入 修复办法 1、修改crmeb/app/api/controller/v1/store/StoreProductController.php文件中的lst方法里面的接收参数&#xff0c;修改成下图 如果你的版本没有coupon_category_id参数的话&#xff0c;…

No.19 笔记 | WEB安全 - 任意文件操作详解 part 1

1. 任意文件上传漏洞基础 什么是文件上传功能? 在网站和应用中,我们经常会看到允许用户上传文件的功能,比如: 更换头像:让用户上传自己的照片作为头像发布图片:在社交媒体或论坛上传图片提交文档:在办公系统中上传Word、Excel等文档 这些都是常见的文件上传功能。 任意文…