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

491.递增子序列

https://programmercarl.com/0491.%E9%80%92%E5%A2%9E%E5%AD%90%E5%BA%8F%E5%88%97.html

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

思路

int* path;
int pathTop;
int** ans;
int ansTop;
int* length;
void copy() {int* tempPath = (int*)malloc(sizeof(int) * pathTop);memcpy(tempPath, path, pathTop * sizeof(int));length[ansTop] = pathTop;ans[ansTop++] = tempPath;
}
int find(int* uset, int usetSize, int key) {int i;for(i = 0; i < usetSize; i++) {if(uset[i] == key)return 1;}return 0;
}
void backTracking(int* nums, int numsSize, int startIndex) {if(pathTop > 1) {copy();}int* uset = (int*)malloc(sizeof(int) * numsSize);int usetTop = 0;int i;for(i = startIndex; i < numsSize; i++) {if((pathTop > 0 && nums[i] < path[pathTop - 1]) || find(uset, usetTop, nums[i]))continue;uset[usetTop++] = nums[i];path[pathTop++] = nums[i];backTracking(nums, numsSize, i + 1);pathTop--;}
}
int** findSubsequences(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){path = (int*)malloc(sizeof(int) * numsSize);ans = (int**)malloc(sizeof(int*) * 33000);length = (int*)malloc(sizeof(int*) * 33000);pathTop = ansTop = 0;backTracking(nums, numsSize, 0);*returnSize = ansTop;*returnColumnSizes = (int*)malloc(sizeof(int) * ansTop);int i;for(i = 0; i < ansTop; i++) {(*returnColumnSizes)[i] = length[i];}return ans;
}

学习反思

用于寻找序列中的递增子序列。算法主要分为两个函数,backTracking和findSubsequences。backTracking函数是递归的回溯函数,用于生成递增子序列。函数中使用了一个辅助数组path来存储当前的递增子序列,pathTop表示当前path数组中元素的个数。在backTracking函数中,首先判断pathTop的值,如果大于1,则将path数组的内容复制到ans数组中,并更新ansTop的值(ansTop表示ans数组中元素的个数)。然后,创建一个辅助数组uset来存储已经使用过的元素,并用usetTop表示uset中元素的个数。接着,从startIndex开始遍历nums数组,对于每个元素,判断是否满足两个条件:当前元素小于path中最后一位元素,或者在uset中已经存在相同的元素。如果满足条件,则继续遍历下一个元素。如果不满足条件,则将当前元素放入uset数组,并将其放入path数组中,然后递归调用backTracking函数,继续生成递增子序列。最后,需要注意在回溯时将pathTop减1,以便继续遍历下一个元素。findSubsequences函数是主函数,用于调用backTracking函数并返回结果。在函数中,首先对辅助数组进行初始化,并调用backTracking函数生成递增子序列。然后,根据生成的递增子序列更新返回的结果数组returnSize和returnColumnSizes。最后,返回结果数组ans。

46.全排列

https://programmercarl.com/0047.%E5%85%A8%E6%8E%92%E5%88%97II.html

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

思路

int* path;
int pathTop;
int** ans;
int ansTop;
void initialize(int* used, int usedLength) {int i;for(i = 0; i < usedLength; i++) {used[i] = 0;}
}
void copy() {int* tempPath = (int*)malloc(sizeof(int) * pathTop);int i;for(i = 0; i < pathTop; i++) {tempPath[i] = path[i];}ans[ansTop++] = tempPath;
}
void backTracking(int* nums, int numsSize, int* used) {if(pathTop == numsSize) {copy();return;}int i;for(i = 0; i < numsSize; i++) {if(used[i])continue;used[i] = 1;path[pathTop++] = nums[i];backTracking(nums, numsSize, used);pathTop--;used[i] = 0;}
}
int** permute(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){path = (int*)malloc(sizeof(int) * numsSize);ans = (int**)malloc(sizeof(int*) * 1000);int* used = (int*)malloc(sizeof(int) * numsSize);initialize(used, numsSize);ansTop = pathTop = 0;backTracking(nums, numsSize, used);*returnSize = ansTop;*returnColumnSizes = (int*)malloc(sizeof(int) * ansTop);int i;for(i = 0; i < ansTop; i++) {(*returnColumnSizes)[i] = numsSize;}return ans;
}

学习反思

使用回溯算法来求解给定数组的全排列。通过不断选择未使用的元素,将其加入当前排列中,并递归搜索剩下的元素,直到得到一个完整的排列。然后将排列复制到结果数组中,并回溯到上一步,继续搜索其他可能的排列。在函数permute中,首先初始化辅助变量path、ans和used。其中path用于存储当前排列,ans用于存储所有的排列,used用于标记元素是否已经被使用过。然后调用backTracking函数开始回溯算法。backTracking函数是实现回溯算法的核心部分。在每一次递归中,首先判断是否已经找到一个完整的排列。如果是,则将当前排列复制到结果数组ans中,并返回。否则,遍历数组nums中的所有元素,对于未使用的元素,将其加入当前排列path中,并将对应的used数组标记为已使用。然后递归调用backTracking函数继续搜索剩下的元素。在递归返回后,需要回溯,即将path中的元素移除,将used数组标记为未使用。最后,在permute函数中设置返回结果的格式,返回结果数组ans,并设置每个排列的长度为numsSize。这段代码的时间复杂度为O(n!)。

N皇后

思路

char ***ans;
char **path;
int ansTop, pathTop;
void copyPath(int n) {char **tempPath = (char**)malloc(sizeof(char*) * pathTop);int i;for(i = 0; i < pathTop; ++i) {tempPath[i] = (char*)malloc(sizeof(char) * n + 1);int j;for(j = 0; j < n; ++j)tempPath[i][j] = path[i][j];tempPath[i][j] = '\0';}ans[ansTop++] = tempPath;
}
int isValid(int x, int y, int n) {int i, j;for(i = 0; i < n; ++i) {if(path[y][i] == 'Q' || path[i][x] == 'Q')return 0;}i = y - 1;j = x - 1;while(i >= 0 && j >= 0) {if(path[i][j] == 'Q')return 0;--i, --j;}i = y + 1;j = x + 1;while(i < n && j < n) {if(path[i][j] == 'Q')return 0;++i, ++j;}i = y - 1;j = x + 1;while(i >= 0 && j < n) {if(path[i][j] == 'Q')return 0;--i, ++j;}i = y + 1;j = x -1;while(j >= 0 && i < n) {if(path[i][j] == 'Q')return 0;++i, --j;}return 1;
}
void backTracking(int n, int depth) {if(pathTop == n) {copyPath(n);return;}int i;for(i = 0; i < n; ++i) {if(isValid(i, depth, n)) {path[depth][i] = 'Q';++pathTop;backTracking(n, depth + 1);path[depth][i] = '.';--pathTop;}}
}
void initPath(int n) {int i, j;for(i = 0; i < n; i++) {path[i] = (char*)malloc(sizeof(char) * n + 1);for(j = 0; j < n; j++)path[i][j] = '.';path[i][j] = '\0';}
}char *** solveNQueens(int n, int* returnSize, int** returnColumnSizes){ans = (char***)malloc(sizeof(char**) * 400);path = (char**)malloc(sizeof(char*) * n);ansTop = pathTop = 0;initPath(n);backTracking(n, 0);*returnSize = ansTop;int i; *returnColumnSizes = (int*)malloc(sizeof(int) * ansTop);for(i = 0; i < ansTop; ++i) {(*returnColumnSizes)[i] = n;}return ans;
}

学习反思

解决N皇后问题的回溯算法实现。首先定义了ans和path两个全局变量,用于存储结果和当前路径。ans是一个三维字符数组,表示所有解的集合。path是一个二维字符数组,表示当前路径的棋盘状态。copyPath函数用于将path中的元素复制到ans中。首先根据pathTop的大小动态分配tempPath的空间,然后逐个复制path中的元素到tempPath中,并在最后加入'\0'作为字符串结尾。完成复制后,将tempPath赋值给ans[ansTop],并将ansTop自增1。isValid函数用于判断当前位置是否有效。首先通过两个for循环检查同一行和同一列是否有皇后,如果有则返回0表示无效。然后通过四个while循环检查两个斜角方向是否有皇后,如果有则返回0表示无效。最后返回1表示有效。backTracking函数是核心递归函数,用于将皇后放置到棋盘上。首先判断pathTop的大小是否等于n,如果是则说明path中已经有n个皇后,将path复制到ans中,然后返回上一层。否则,遍历当前行的每个位置,如果当前位置有效,则将皇后放置到该位置,然后调用backTracking函数递归下一行,递归完成后进行回溯,将当前位置的皇后移除,继续遍历下一个位置。initPath函数用于初始化path数组,将所有元素设为'.'。首先通过两个for循环分别为path中的每个char*开辟空间,并将所有字符设为'.'。在每个字符串的结尾加入'\0'作为字符串结尾。solveNQueens函数是整体的解决函数。首先初始化ans、path、ansTop和pathTop等变量。然后调用initPath函数初始化path数组。接着调用backTracking函数进行回溯算法。最后设置返回数组的大小和每个解的列数,并返回ans数组。这段代码的时间复杂度为O(n!)。

解数独

https://programmercarl.com/0037.%E8%A7%A3%E6%95%B0%E7%8B%AC.html

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

思路

bool isValid(char** board, int row, int col, int k) {for (int i = 0; i < 9; i++) {if (board[i][col] == k) {return false;}}for (int j = 0; j < 9; j++) {if (board[row][j] == k) {return false;}}int startRow = (row / 3) * 3;int startCol = (col / 3) * 3;for (int i = startRow; i < startRow + 3; i++) {for (int j = startCol; j < startCol + 3; j++) {if (board[i][j] == k) {return false;}}}return true;
}bool backtracking(char** board, int boardSize, int* boardColSize) {for (int i = 0; i < boardSize; i++) {for (int j = 0; j < *boardColSize; j++) {/* 遇到数字跳过 */if (board[i][j] != '.') {continue;}for (int k = '1'; k <= '9'; k++) {if (isValid(board, i, j, k)) {board[i][j] = k;if (backtracking(board, boardSize, boardColSize)) {return true;}board[i][j] = '.';}}return false;}}return true;
}
void solveSudoku(char** board, int boardSize, int* boardColSize) {bool res = backtracking(board, boardSize, boardColSize);
}

学习反思

一个解数独问题的算法实现。算法使用回溯法来求解数独。在isValid函数中,首先判断当前位置所在行是否有重复元素,然后判断当前位置所在列是否有重复元素,最后判断当前位置所在的九宫格是否有重复元素。如果有重复元素,则返回false;否则返回true。在backtracking函数中,使用两层循环遍历数独的每个位置。如果当前位置是空格,则依次尝试填入数字1到9并判断是否满足数独规则。如果满足规则,则将当前位置填入数字,并递归调用backtracking函数继续填下一个位置。如果递归返回true,则说明找到一种解法,返回true;如果递归返回false,则回溯,将当前位置清零,并尝试下一个数字。最后,在主函数solveSudoku中调用backtracking函数求解数独。该算法的时间复杂度是O(9^(nn))。

总结

加油!!!

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

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

相关文章

动态规划-子序列问题——300.最长递增子序列

1.题目解析 题目来源&#xff1a;300.最长递增子序列——力扣 测试用例 2.算法原理 1.状态表示 首先创建一个与数组大小相同的dp表&#xff0c;此时dp[i]表示的是&#xff1a;以第i个位置为结尾的所有子序列中最长递增子序列的长度 2.状态转移方程 此时第i个位置一定是最长递…

国家能源集团携手海康威视研发攻克融合光谱煤质快检技术

10月24日&#xff0c;在国家能源集团准能集团黑岱沟露天煤矿&#xff0c;安装于准能选煤厂785商品煤胶带机中部的煤质快检核心设备&#xff0c;正在对当天装车外运的商品煤煤质进行实时检测。仅两分钟后&#xff0c;涵盖发热量、水分、灰分、硫分等多项指标的数据信息已传输到到…

六.python面向对象

学过C或者Java的同学一定了解过面向对象的相关内容&#xff0c;编程语言一般分为两种设计方式&#xff1a;面向对象、面向过程&#xff0c;早期的编程语言多是面向过程的&#xff0c;由多个过程组合在一起&#xff0c;而Python在设计的时候就是一种面向对象的语言&#xff0c;因…

Room新手入门

Room Room 是所谓的 ORM&#xff08;对象关系映射&#xff09;库 依赖 在项目级 build.gradle 文件中&#xff0c;在 ext 代码块中定义 room_version。 ext {kotlin_version "1.6.20"nav_version "2.4.1"room_version 2.4.2 }在应用级 build.gradle…

【JavaEE初阶】深入理解TCP协议中的封装分用以及UDP和TCP在网络编程的区别

前言 &#x1f31f;&#x1f31f;本期讲解关于TCP/UDP协议的原理理解~~~ &#x1f308;上期博客在这里&#xff1a;【JavaEE初阶】入门视角-网络原理的基础理论的了解-CSDN博客 &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSDN博客 &#x1f525; …

【Spring】关于Spring中aware相关接口的作用

Aware 接口的回调方法是在 Bean 实例化之后调用的。具体来说&#xff0c;这些回调方法是在依赖注入完成后&#xff0c;但在 Bean 完全初始化之前调用的。这是 Spring 容器管理 Bean 生命周期的一部分 完成了属性赋值之后&#xff0c;Spring会执行一些回调&#xff0c;包括&…

java中Set,Map,List集合的比较(不包含增删改查函数方法)

目录 1. 集合的简介2. List3. Set4. Map5. 比较5.1 结构特点5.2 实现类5.3 区别 6. 其他问题6.1 集合与数组的区别6.2 哪些集合类是线程安全的 7. 参考链接 1. 集合的简介 所有的集合类和集合接口都在java.util包下。 在内存中申请一块空间用来存储数据&#xff0c;在Java中集…

langchain的使用以及算力的计算

文章目录 提示词提示词 import warnings warnings.filterwarnings("ignore") from langchain import PromptTemplate,LLMChain from llm import ChatGLM# 简单的问题模板 template = """问题: {question}答案: """ prompt = PromptTe…

C++加载sqlite3数据库文件

db数据库文件简单轻便&#xff0c;形式上可以像excel数据那样&#xff0c;但是解析的时候却有很大的灵活性。使用Python解析db数据已经是很简单的事情&#xff0c;使用专门的数据库可视化工具&#xff0c;通过sql语句查询内容也是有手就行&#xff0c;也许C也不难&#xff0c;但…

31省226地级市极端天气和气候风险指数 (1993-2023年)附下载链接

1993-2023年31省、226个地级市极端天气和气候风险指数 下载链接-点它&#x1f449;&#x1f449;&#xff1a;1993-2023年31省、226个地级市极端天气和气候风险指数-最新出炉.zip 数据名称 1993&#xff5e;2023 省市级气候风险指数 数据来源 nature 子刊&#xff0c;已转…

DEPT:DECOMPOSED PROMPT TUNING FOR PARAMETER-EFFICIENT FINE-TUNING

论文汇总 当前的问题 (1)Prompt Tuning通常收敛缓慢&#xff0c;并且对初始化敏感&#xff1b; (2)Prompt Tuning延长了输入序列的总长度&#xff0c;从而加剧了计算需求(即训练/推理时间和内存成本)&#xff0c;这是由于Transformer的二次复杂度(Vaswani et al, 2017)。 解…

鸿蒙开发:实现全局异常捕获和异常查看

前言 开发中的异常信息&#xff0c;我们很容易排查&#xff0c;直接可以在控制台中就可以查看&#xff0c;但是&#xff0c;提交给测试同学或者上线后的异常信息&#xff0c;我们如何获取呢&#xff1f;这里我们很容易想起&#xff0c;三方sdk&#xff0c;比如常见的腾讯Bugly…

基于Springboot+Vue的学校课程管理系统(含源码数据库)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 这个系…

vue之打包配置环境

一直以来都是用脚手架直接搭建的项目,也很少去深究,前两天因为环境配置变更,稍微研究了下 NODE_ENV 首先 在evn.xxx 的配置文件里 一定要有的NODE_ENV NODE_ENV 默认只有两种状态即development和production development: 指代本地开发即localhost环境&#xff08;本地的开发…

VirtualBox虚拟机桥接模式固定ip详解

VirtualBox虚拟机桥接模式固定ip详解 VirtualBox 桥接设置Ubuntu 24.04使用固定IP问题记录 VirtualBox 桥接设置 为什么设置桥接模式&#xff1f;桥接模式可以实现物理机和虚拟机互相通信&#xff0c;虚拟机也可以访问互联网&#xff08;推荐万金油&#xff09;&#xff0c;物…

EIR管理机卡绑定配置

EIR&#xff08;Equipment Identity Register&#xff09;管理中的机卡绑定配置通常涉及到设备与SIM卡的关系维护&#xff0c;以确保网络能够正确识别和管理设备的身份。下面是关于EIR管理支持机卡绑定配置的一些主要步骤和概念&#xff1a; 1. 概念介绍 机卡绑定&#xff1a…

2020款Macbook Pro A2251无法充电无法开机定位及修复

问题背景 up主有一台2020年的Macbook Pro&#xff0c;带Touch Bar&#xff0c;16G512G&#xff0c;四核I5&#xff0c;型号A2251 应该是一周没充电了&#xff0c;之前还用的好好的&#xff0c;后来有一天出差想带上 打开没电&#xff0c;手头上有个小米的66W快充头&#xff0c…

LeetCode常用算法模板

代码模板 1、DFS&#xff1a;适用于树和图的遍历、组合问题。 2、BFS&#xff1a;适用于树和图的层次遍历、最短路径问题。 3、二分查找&#xff1a;适用于有序数组的搜索问题。 4、动态规划&#xff1a;适用于最优化问题、序列问题。 5、贪心算法&#xff1a;适用于局部最优问…

(二)Windows通过vs c++编译PaddleOCR-2.8.1

编译环境 操作系统&#xff1a;windows 11 paddleOCR版本&#xff1a;2.8.1 opencv版本&#xff1a;4.10.0 cmake版本&#xff1a;3.22.6 git版本&#xff1a;2.47.0 visual statio版本&#xff1a;VS 2022 Community&#xff08;选择社区版本即可&#xff0c;安装时记得…

python离线安装依赖

以pymsql依赖为例操作如下: Python Package Index&#xff08;PyPI&#xff09;的官方网址是&#xff1a; PyPI The Python Package Index 在这个网站上&#xff0c;你可以搜索、浏览和下载Python包。 tar -xvzf pymysql2-1.3.3.tar.gz cd pymysql2-1.3.3 python setup.p…