【算法篇】回溯算法类(1)(笔记)

目录

一、理论基础

1. 相关题目

2. 遍历过程

3. 代码框架 

二、LeetCode 题目

1. 组合

2. 组合总和III

3. 电话号码的字母组合

4. 组合总和

5. 组合总和II

6. 分割回文串

7. 复原IP地址

8. 子集


一、理论基础

1. 相关题目

2. 遍历过程

3. 代码框架 

void backtracking(参数) {if (终止条件) {存放结果;return;}for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {处理节点;backtracking(路径,选择列表); // 递归回溯,撤销处理结果}
}

二、LeetCode 题目

1. 组合

https://leetcode.cn/problems/combinations/description/icon-default.png?t=O83Ahttps://leetcode.cn/problems/combinations/description/

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

 

class Solution {
public:vector<vector<int>> result;vector<int> path;void backtracking(int n, int k, int startIndex) {// 满足条件插入if (path.size() == k) {result.push_back(path);return;}// 如果后面的数组满足不了能取出 k - path.size() 个数组,则不用遍历了for (int i = startIndex; i <= n - (k - path.size()) + 1; i++) {path.push_back(i);backtracking(n, k, i + 1);path.pop_back();}return;}vector<vector<int>> combine(int n, int k) {backtracking(n, k, 1);return result;}
};

2. 组合总和III

https://leetcode.cn/problems/combination-sum-iii/description/icon-default.png?t=O83Ahttps://leetcode.cn/problems/combination-sum-iii/description/

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

  • 只使用数字 1 到 9
  • 每个数字 最多使用一次 

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

示例 1:
输入: k = 3, n = 7
输出: [[1,2,4]]
解释:
1 + 2 + 4 = 7
没有其他符合的组合了。示例 2:
输入: k = 3, n = 9
输出: [[1,2,6], [1,3,5], [2,3,4]]
解释:
1 + 2 + 6 = 9
1 + 3 + 5 = 9
2 + 3 + 4 = 9
没有其他符合的组合了。示例 3:
输入: k = 4, n = 1
输出: []
解释: 不存在有效的组合。
在[1,9]范围内使用4个不同的数字,我们可以得到的最小和是1+2+3+4 = 10,因为10 > 1,没有有效的组合。

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

3. 电话号码的字母组合

https://leetcode.cn/problems/letter-combinations-of-a-phone-number/description/icon-default.png?t=O83Ahttps://leetcode.cn/problems/letter-combinations-of-a-phone-number/description/

        给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

示例 1:
输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]示例 2:
输入:digits = ""
输出:[]示例 3:
输入:digits = "2"
输出:["a","b","c"]

class Solution {
private:const string letterMap[10] = {"", // 0"", // 1"abc", // 2"def", // 3"ghi", // 4"jkl", // 5"mno", // 6"pqrs", // 7"tuv", // 8"wxyz", // 9};
public:vector<string> result;string s;void backtracking(const string& digits, int index) {if (index == digits.size()) {result.push_back(s);return;}int digit = digits[index] - '0';        // 将index指向的数字转为intstring letters = letterMap[digit];      // 取数字对应的字符集for (int i = 0; i < letters.size(); i++) {s.push_back(letters[i]);            // 处理backtracking(digits, index + 1);    // 递归,注意index+1,一下层要处理下一个数字了s.pop_back();                       // 回溯}}vector<string> letterCombinations(string digits) {s.clear();result.clear();if (digits.size() == 0) {return result;}backtracking(digits, 0);return result;}
};

4. 组合总和

https://leetcode.cn/problems/combination-sum/description/icon-default.png?t=O83Ahttps://leetcode.cn/problems/combination-sum/description/

        给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。

        candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。 

        对于给定的输入,保证和为 target 的不同组合数少于 150 个。

示例 1:
输入:candidates = [2,3,6,7], 
target = 7
输出:[[2,2,3],[7]]
解释:
2 和 3 可以形成一组候选,2 + 2 + 3 = 7 。注意 2 可以使用多次。
7 也是一个候选, 7 = 7 。
仅有这两种组合。示例 2:
输入: candidates = [2,3,5], target = 8
输出: [[2,2,2,2],[2,3,3],[3,5]]示例 3:
输入: candidates = [2], target = 1
输出: []

class Solution {
public:vector<vector<int>> result;vector<int> record;void backtracking(vector<int>& candidates, int targetnum, int sum, int startIndex) {if (sum == targetnum) {result.push_back(record);return;}for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= targetnum; i++) {record.push_back(candidates[i]);backtracking(candidates, targetnum, sum + candidates[i], i);record.pop_back();}return;}vector<vector<int>> combinationSum(vector<int>& candidates, int target) {sort(candidates.begin(), candidates.end()); // 需要排序backtracking(candidates, target, 0, 0);return result;}
};

5. 组合总和II

https://leetcode.cn/problems/combination-sum-ii/description/icon-default.png?t=O83Ahttps://leetcode.cn/problems/combination-sum-ii/description/

        给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

        candidates 中的每个数字在每个组合中只能使用 一次 。

        注意:解集不能包含重复的组合。 

示例 1:
输入: candidates = [10,1,2,7,6,1,5], target = 8,
输出:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]示例 2:
输入: candidates = [2,5,2,1,2], target = 5,
输出:
[
[1,2,2],
[5]
]

// 方法一:
class Solution {
public:vector<vector<int>> result;vector<int> path;void backtracking(vector<int>& candidates, int startIndex, int target) {if (target == 0) {result.push_back(path);return;}for (int i = startIndex; i < candidates.size() && target - candidates[i] >= 0; i++) {if (i > startIndex && candidates[i] == candidates[i - 1]) {continue;}path.push_back(candidates[i]);backtracking(candidates, i + 1, target - candidates[i]);path.pop_back();}return;}vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {sort(candidates.begin(), candidates.end());backtracking(candidates, 0, target);return result;}
};// 方法二:
class Solution {
public:vector<vector<int>> result;vector<int> path;void backtracking(vector<int>& candidates, int startIndex, int target) {if (target == 0) {result.push_back(path);return;}unordered_set<int> uset;for (int i = startIndex; i < candidates.size() && target - candidates[i] >= 0; i++) {if (uset.find(candidates[i]) != uset.end()) {continue;}uset.insert(candidates[i]);path.push_back(candidates[i]);backtracking(candidates, i + 1, target - candidates[i]);path.pop_back();}return;}vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {sort(candidates.begin(), candidates.end());backtracking(candidates, 0, target);return result;}
};

6. 分割回文串

https://leetcode.cn/problems/palindrome-partitioning/description/icon-default.png?t=O83Ahttps://leetcode.cn/problems/palindrome-partitioning/description/

        给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。

示例 1:
输入:s = "aab"
输出:[["a","a","b"],["aa","b"]]示例 2:
输入:s = "a"
输出:[["a"]]

class Solution {
public:vector<vector<string>> result;vector<string> st;void backtracking(const string s, int beginIndex) {// 找到一种切割方法if (beginIndex == s.size()) {result.push_back(st);return;}for (int i = beginIndex; i < s.size(); i++) {if (isPalindrome(s, beginIndex, i)) {// 是回文子串,保存st.push_back(s.substr(beginIndex, i - beginIndex + 1));}else {continue;}backtracking(s, i + 1);st.pop_back();}return;}bool isPalindrome(const string s, int begin, int end) {for (int i = begin, j = end; i < j; i++, j--) {if (s[i] != s[j]) return false;}return true;}vector<vector<string>> partition(string s) {backtracking(s, 0);return result;}
};

7. 复原IP地址

https://leetcode.cn/problems/restore-ip-addresses/description/icon-default.png?t=O83Ahttps://leetcode.cn/problems/restore-ip-addresses/description/

        有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 '.' 分隔。

  • 例如:"0.1.2.201" 和 "192.168.1.1" 是 有效 IP 地址,但是 "0.011.255.245""192.168.1.312" 和 "192.168@1.1" 是 无效 IP 地址。

        给定一个只包含数字的字符串 s ,用以表示一个 IP 地址,返回所有可能的有效 IP 地址,这些地址可以通过在 s 中插入 '.' 来形成。你 不能 重新排序或删除 s 中的任何数字。你可以按 任何 顺序返回答案。

示例 1:
输入:s = "25525511135"
输出:["255.255.11.135","255.255.111.35"]示例 2:
输入:s = "0000"
输出:["0.0.0.0"]示例 3:
输入:s = "101023"
输出:["1.0.10.23","1.0.102.3","10.1.0.23","10.10.2.3","101.0.2.3"]

// 版本一:
class Solution {
public:vector<string> result;vector<string> st;void backtracking(const string s, int beginIndex) {if (beginIndex == s.size()) {if (st.size() == 4) {string buff = st.front();for (int j = 1; j < 4; j++)  buff = buff + "." + st[j];result.push_back(buff);return;}else {return;}}for (int i = beginIndex; i < s.size(); i++) {if (judgeNum(s, beginIndex, i)) {// 在范围内st.push_back(s.substr(beginIndex, i - beginIndex + 1));backtracking(s, i + 1);st.pop_back();}else {break;}}return;}bool judgeNum(const string& s, int start, int end) {if (start > end) {return false;}if (s[start] == '0' && start != end) { // 0开头的数字不合法return false;}int num = 0;for (int i = start; i <= end; i++) {if (s[i] > '9' || s[i] < '0') { // 遇到非数字字符不合法return false;}num = num * 10 + (s[i] - '0');if (num > 255) { // 如果大于255了不合法return false;}}return true;
}vector<string> restoreIpAddresses(string s) {backtracking(s, 0);return result;}
};// 版本二:
class Solution {
private:vector<string> result;  // 记录结果// startIndex: 搜索的起始位置,pointNum:添加逗点的数量void backtracking(string& s, int startIndex, int pointNum) {if (pointNum == 3) { // 逗点数量为3时,分隔结束// 判断第四段子字符串是否合法,如果合法就放进result中if (isValid(s, startIndex, s.size() - 1)) {result.push_back(s);}return;}for (int i = startIndex; i < s.size(); i++) {if (isValid(s, startIndex, i)) { // 判断 [startIndex, i] 这个区间的子串是否合法s.insert(s.begin() + i + 1 , '.');  // 在i的后面插入一个逗点pointNum++;backtracking(s, i + 2, pointNum);   // 插入逗点之后下一个子串的起始位置为i+2pointNum--;                         // 回溯s.erase(s.begin() + i + 1);         // 回溯删掉逗点} else {break; // 不合法,直接结束本层循环}}}// [start, end]bool isValid(const string& s, int start, int end) {if (start > end) {return false;}if (s[start] == '0' && start != end) { // 0开头的数字不合法return false;}int num = 0;for (int i = start; i <= end; i++) {if (s[i] > '9' || s[i] < '0') { // 遇到非数字字符不合法return false;}num = num * 10 + (s[i] - '0');if (num > 255) { // 如果大于255了不合法return false;}}return true;}public:vector<string> restoreIpAddresses(string s) {result.clear();if (s.size() < 4 || s.size() > 12) return result; // 算是剪枝了backtracking(s, 0, 0);return result;}
};

8. 子集

https://leetcode.cn/problems/subsets/description/icon-default.png?t=O83Ahttps://leetcode.cn/problems/subsets/description/

        给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

示例 1:
输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]示例 2:
输入:nums = [0]
输出:[[],[0]]

class Solution {
public:vector<vector<int>> result;vector<int> vec;void backtracking(vector<int>& nums, int beginIndex) {result.push_back(vec);if (beginIndex >= nums.size()) {return;}for (int i = beginIndex; i < nums.size(); i++) {vec.push_back(nums[i]);backtracking(nums, i + 1);vec.pop_back();}return;}vector<vector<int>> subsets(vector<int>& nums) {if (nums.size() == 0) return result;backtracking(nums, 0);return result;}
};

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

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

相关文章

SSM环卫人员管理平台—计算机毕业设计源码36412

目 录 摘要 1 绪论 1.1背景及意义 1.2国内外研究概况 1.3研究内容 1.4 ssm框架介绍 1.5论文结构与章节安排 2 环卫人员管理平台系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1数据增加流程 2.2.2数据修改流程 2.2.3数据删除流程 2.3 系统功能分析 2.3.1 功能性…

JAVAIDEA初始工程的创建

四结构 建工程综述* 初始*&#xff1a; 1、先建个空项目&#xff0c; 2、打开文件中的项目结构新建module模块&#xff08;模块下有src&#xff09; 修改模块名&#xff1a; 也是Refactor&#xff0c;Rename&#xff0c;但是要选第三个同时改模块和文件夹名字 导入模块&am…

C++——模拟实现vector

1.查看vector的源代码 2.模拟实现迭代器 #pragma oncenamespace jxy {//模板尽量不要分离编译template <class T>class vector{public:typedef T* iterator;//typedef会受到访问限定符的限制typedef const T* const_iterator;//const迭代器是指向的对象不能修改&#xf…

开发和软件工程一样吗?

时间&#xff1a;2024年 10月 02日 作者&#xff1a;小蒋聊技术 邮箱&#xff1a;wei_wei10163.com 微信&#xff1a;wei_wei10 音频&#xff1a;喜马拉雅 大家好&#xff0c;欢迎来到“小蒋聊技术”&#xff0c;我是小蒋&#xff01; 今天咱们要聊的话题是——开发和软件工…

17.反射与动态代理

目录 1.反射的概述 2.学习反射到底学什么&#xff1f; 3.字节码文件和字节码文件对象 4.获取字节码文件对象的三种方式 5.Class类中用于获取构造方法的方法 6.Class类中用于获取成员变量的方法 7.Class类中用于获取成员方法的方法 8.反射和配置文件结合动态获取的练习与利用反…

Java类和对象、自定义包、static、代码块、方法重写

目录 1.类和对象 2.this指针 3.对象的构造和初始化 3.1默认初始化 3.2就地初始化 3.3构造初始化 3.4IDEA快速填充 3.5使用this简化 3.6初始化的总结 4.包的引入 4.1包的概念 4.2导入包中的类 4.3自定义包 5.static修饰 6.代码块的划分 7.方法重写 1.类和对象 使…

C++系列-多态

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 多态 多态就是不同类型的对象&#xff0c;去做同一个行为&#xff0c;但是产生的结果是不同的。 比如说&#xff1a; 都是动物叫声&#xff0c;猫是喵喵&#xff0c;狗是汪汪&am…

rancher hello-world

创建一个Deployment, 只填名称和容器镜像rancher/hello-world 成功后: 查看日志 结果&#xff1a; 部署了工作负载。这个过程可能需要几分钟完成。 当您的工作负载部署完成后&#xff0c;它的状态将变为Active&#xff0c;您可以从项目的工作负载页面查看工作负载当前的状态…

ARM assembly: Lesson 10

今天&#xff0c;我们来看一下基于ARM汇编&#xff0c;如何实现函数的调用。 基础知识 在ARM汇编中&#xff0c;函数的前四个参数存放于 R0~R3寄存器中, 剩余的参数存放于栈中&#xff0c;返回值存放于r0。在栈中存放数值&#xff0c;可以避免在调用过程中&#xff0c;数据的…

串--KMP算法之手动计算next数组(详解)

目录 一、手动计算next数组 二、使用next数组进行模式匹配 三、练习 一、手动计算next数组 next[2] 表示模式串和主串对比&#xff0c;模式串里面第2个字符和主串不匹配&#xff0c;j应该指向几&#xff1f; 首先&#xff1a;字符串的下标和next数组下标保持一致 字符串是1~…

初识TCP/IP协议

回顾上文 来回顾一下TCP协议的特性&#xff0c;有一道比较经典的题&#xff1a;如何使用UDP实现可靠传输&#xff0c;通过应用程序的代码&#xff0c;完成可靠传输的过程&#xff1f; 原则&#xff0c;TCO有啥就吹啥&#xff0c;引入滑动窗口&#xff0c;引入流量控制&#x…

计算机毕业设计 农场投入品运营管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

ECP5701:PD协议芯片兼容PD 2.0和PD 3.0 (5V,9V,12V,15V,20V),支持 PD 输入多种类型无线充方案

TYPE-C接口&#xff0c;全称USB Type-C&#xff0c;是近年来在电子设备中广泛采用的一种新型接口。它以其小巧的尺寸、可逆的插拔方向以及高速的数据传输能力&#xff0c;迅速取代了传统的USB接口&#xff0c;成为现代设备的标准配置。不仅如此&#xff0c;TYPE-C接口还支持PD&…

2024年音频转文字:不可错过的四大工具!

在数字化办公和学习的背景下&#xff0c;音频转文字服务正变得越来越重要。本文将针对几款备受推崇的音频转文字工具进行深入解析&#xff01; 365在线转文字&#xff1a;云端处理&#xff0c;无需下载 直达链接&#xff1a;www.pdf365.cn/ 365在线转文字以其高效的转录速度…

Pikachu-Cross-Site Scripting-存储型xss

存储型xss &#xff0c;随便输入点内容&#xff0c;都能保存下来&#xff1b;刷新后也不会丢失&#xff1b;输入特殊字符&#xff0c;也能原样返回&#xff1b; 查看代码&#xff0c;也可以看到输出结果直接原路返回&#xff0c;不做处理 构造payload <script>alert(1)…

batch和momentum

&#x1f680; 机器学习系列前期回顾 1、初识机器学习 2、线性模型到神经网络 3、local minima的问题如何解决 &#x1f680;在初识机器学习中&#xff0c;了解了机器学习是如何工作的并引入了线性模型&#xff0c;在线性模型到神经网络这节&#xff0c;将线性模型进一步改进为…

【web安全】——XSS漏洞

1.XSS漏洞基础 1.1.漏洞成因 XSS(Cross-site scripting)被称为跨站脚本攻击&#xff0c;由于与层叠样式表的缩写一样&#xff0c;因此被缩写为XSS.XSS漏洞形成的原因是网站/程序对前端用户的输入过滤不严格&#xff0c;导致攻击者可以将恶意的is/html代码注入到网页中&#x…

基于Word2Vec和LSTM实现微博评论情感分析

关于深度实战社区 我们是一个深度学习领域的独立工作室。团队成员有&#xff1a;中科大硕士、纽约大学硕士、浙江大学硕士、华东理工博士等&#xff0c;曾在腾讯、百度、德勤等担任算法工程师/产品经理。全网20多万粉丝&#xff0c;拥有2篇国家级人工智能发明专利。 社区特色…

【Python报错已解决】TypeError: unsupported operand type(s) for +: ‘str‘ and ‘int‘

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 专栏介绍 在软件开发和日常使用中&#xff0c;BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…

【C++前缀和】2845. 统计趣味子数组的数目|2073

本文涉及的基础知识点 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 LeetCode 2845. 统计趣味子数组的数目 难度分&#xff1a;2073 给你一个下标从 0 开始的整数数组 nums &#xff0c;以及整数 modulo 和整数 k 。 请你找出并统计数组…