代码随想录——回溯

这篇具有很好参考价值的文章主要介绍了代码随想录——回溯。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

系列文章目录

代码随想录——回溯



概述

回溯的本质就是递归遍历,但在完成某一条路之后会撤回到上一层,然后重新选择另一条路继续遍历,是一个比较低效的算法,能进行提升的方式就是剪枝。

void backtracking(参数) {
    if (终止条件) {
        存放结果;
        return;
    }

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

代码随想录——回溯,c++,学习,笔记,算法,leetcode,代码随想录

组合

组合

链接:https://leetcode.cn/problems/combinations/description/

vector<vector < int > > 作为最终返回的结果,vector < int >作为每一小项,中止条件是vector< int > == k,注意在递归过程中n,k是不变的,所以必须引入一个递增index来去重。

剪枝方法:

  1. 已经选择的元素个数:path.size();
  2. 还需要的元素个数为: k - path.size();
  3. 在集合n中至多要从该起始位置 : n - (k - path.size()) + 1,开始遍历

组合III

链接:https://leetcode.cn/problems/combination-sum-iii/description/

与前一个组合几乎一样,但中止条件需要加一个total == k的判断。

电话号码的字母组合

链接:https://leetcode.cn/problems/letter-combinations-of-a-phone-number/description/

中止条件是单个项的size等于digits的size,一开始我以为要双循环,即digits遍历和单个数字对应的字母遍历,但其实不需要,因为digits一定是顺序往后取的,所以只需要定义一个index,每层递归+1即可。
ps:在leetcode由char转变为int的方法是减去 ‘0’

num[digits[index] - '0'

组合总和

链接:https://leetcode.cn/problems/combination-sum/description/
中止条件为当总和相等时push进result并return,总和超过target时直接人return;注意这道题也是不能重复的,一般不能重复的都需要加入index来保证起始位置。

组合总和II

链接:https://leetcode.cn/problems/combination-sum-ii/description/
这道题不重复的核心点在于,同层的数不能够重选,例如[1,1,2,2,5],第一层选了1,第二层还是可以继续选1,因为两者不是同层的。但如果第一层的第一个1用完了,又选了第二个1,这就重复了,所以只需要加一个判断条件:

            if (i > index && candidates[i] == candidates[i - 1]) {
                continue;
            }

这里的核心点在于ℹi > index,因为index是本层的第一个数,必然不可能重复,所以要从index下一个开始判断,此时如果第二个数和第一个数是相同的,则属于同层重复选择,直接continue;

分割

分割回文串

https://leetcode.cn/problems/palindrome-partitioning/description/
每切下来一个子字符串,就相当于是在一层做了选择,这样就可以套上回溯算法的模板。中止条件是起始切割位置到了字符串的最后一位,额外再写一个回文判断函数。、
注意:leetcode里常用的切割字符串函数substr,第一个参数是起始位置,第二个参数是要切割的长度。

string str = s.substr(index,i - index + 1);

** 复原ip地址

https://leetcode.cn/problems/restore-ip-addresses/description/
这道题一直做错,能接受的方法是,将切割每一个子字符串进行判断,符合标准后放入vector备用,个数达到4个并且index也等于s.size()之后,再拼接放入最终的result里。
注意:string转为int直接用stoi函数

return stoi(s) <= 255;

字符串的增加和删改不能用-=和+=,要用insert和erase。

子集

子集

https://leetcode.cn/problems/subsets/description/
这道题唯一要注意的点是子集的大小是不固定的,所以不能在中止条件里面将子集添加到结果里,每一次循环都要添加,所以放在递归的开头。中止条件是index == s.size()。

子集II

https://leetcode.cn/problems/subsets-ii/description/
这题和之前组合的去重思路一模一样,在子集的基础上,首先对nums进行sort保证是递增的,然后进行判断去掉本层重复的选择。

if(i > index && nums[i] == nums[i - 1]) continue;

全排列

全排列

https://leetcode.cn/problems/permutations/description/
全排列不需要用到index,index只有不能从头重复拿的问题需要用的,全排列需要从头拿,但怎么保证去重呢,就把取过的数暂存到temp,并将这个数重新赋值一个不会取到的数,回溯过程中再放回来。循环过程中,对数进行判断,如果是那个不会取到的数,就直接跳过,从而达到去重的效果。

全排列II

https://leetcode.cn/problems/permutations-ii/description/
和之前的去重操作一样,先sort然后本层去重。

棋盘问题

N皇后

https://leetcode.cn/problems/n-queens/description/
比较好的思路是先创建一个n*n的棋盘,每一行放置Q的时候,对这个位置进行判断,判断函数的只需要判断这一层之上是否满足就可以了,中止条件是层数 == n。
注意:

  1. 引用传递会比值传递节省巨幅的空间和时间,尽量使用引用传递。
  2. for循环的判断条件,用逗号时相当于只有最后一个生效!!!
for (int i = 5, j = 3; i >= 0, j >= 0; i--, j--) {
    // 在这里,条件实际上是 j >= 0
    // 循环体
    cout << "i: " << i << ", j: " << j << endl;
}
for (int i = 5, j = 3; i >= 0 && j >= 0; i--, j--) {
    // 在这里,条件是 i >= 0 && j >= 0
    // 循环体
    cout << "i: " << i << ", j: " << j << endl;
}

***解数独

https://leetcode.cn/problems/sudoku-solver/
写的不好。
这题思路回溯的思想是写两个for循环,然后相当于对每一个空的格子尝试填入数字,如果满足条件则return true,如果9个数字都不满足则回溯。填入数字之前先判断。

其他

***递增子序列

https://leetcode.cn/problems/non-decreasing-subsequences/description/
这道题最大的问题在于不能够sort,并且得保证去重。正常的想法是只要path数量大于2,就放入result。但这样就给去重造成了困难,所以一个很新颖的思路是只有当index == size的时候,才去考虑将结果放入result,这样做的好处是第一个判断条件只要元素大于等于path的最后一个数,就正常迭代,但迭代完成回溯回来的时候,加入了第二个判断条件,即如果元素等于path的最后一个数,因为第一个条件只要大于等于就满足,如果第二个条件判断元素为等于,则说明该元素和上一个元素是相等的,即为同层的重复元素,则直接跳过。非常好的想法!

重新安排行程

https://leetcode.cn/problems/reconstruct-itinerary/description/
还没写。文章来源地址https://www.toymoban.com/news/detail-805216.html

到了这里,关于代码随想录——回溯的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 代码随想录-回溯算法(子集问题)|ACM模式

    目录 前言: 78. 子集 题目描述: 输入输出描述: 思路和想法: 90. 子集 II 题目描述: 输入输出描述: 思路和想法: 491. 递增子序列 题目描述: 输入输出描述: 思路和想法: 如果把 子集问题、组合问题、分割问题都抽象为一棵树的话, 那么组合问题和分割问题都是收集

    2024年02月15日
    浏览(30)
  • 代码随想录阅读笔记-回溯【电话号码的字母组合】

    题目 给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。 示例: 输入:\\\"23\\\" 输出:[\\\"ad\\\", \\\"ae\\\", \\\"af\\\", \\\"bd\\\", \\\"be\\\", \\\"bf\\\", \\\"cd\\\", \\\"ce\\\", \\\"cf\\\"]. 说明:尽管上面的答案是按字典序排列的,但是你可以任意

    2024年04月13日
    浏览(27)
  • 代码随想录——回溯

    代码随想录——回溯 回溯的本质就是递归遍历,但在完成某一条路之后会撤回到上一层,然后重新选择另一条路继续遍历,是一个比较低效的算法,能进行提升的方式就是剪枝。 组合 链接:https://leetcode.cn/problems/combinations/description/ vectorvector int 作为最终返回的结果,vector

    2024年01月19日
    浏览(32)
  • 代码随想录二刷 |回溯 |分割回文串

    131.分割回文串 给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。 返回 s 所有可能的分割方案。 示例: 输入: “aab” 输出: [ [“aa”,“b”], [“a”,“a”,“b”] ] 回溯三部曲 递归函数参数 全局变量数组path存放切割后回文的子串,二维数组result存放结果集 参数

    2024年01月24日
    浏览(31)
  • 代码随想录 Leetcode459. 重复的子字符串(KMP算法)

            此解法读者需要了解什么是KMP算法以及KMP算法中next数组的具体含义才能理解         因为在KMP算法的next数组中,next[index]表示 i ndex之前的最大长度的相同前缀后缀值 ,那么要判断整个字符串中是否由重复字串构成,只需要以下两个条件:         1.next[n - 1] !=

    2024年01月19日
    浏览(53)
  • 代码随想录 - Day34 - 回溯:递增子序列+排列问题

    如果有相等的整数也算递增序列 递增子序列中 至少有两个元素 (遍历的时候不用遍历 nums 中最后一个元素) 题目说了数值范围,所以还可以用哈希表去重,速度比 set() 快很多。 但是,个人觉得没必要,因为放在实际情况中一般不会给数值范围。 全排列,即 [1,2] 和 [2,1] 算作

    2024年02月09日
    浏览(56)
  • 代码随想录Leetcode 343. 整数拆分

            dp[i]表示i所能拆分的最大乘积,则dp[i] 与dp[i - 1]的递推公式是:                 max( 1~n * dp[n ~ 1])

    2024年02月21日
    浏览(40)
  • 代码随想录Leetcode70. 爬楼梯

            空间复杂度为O(N),如果想要优化空间复杂度,则只用三个变量进行状态转移也可以,参考 代码随想录 Leetcode509. 斐波那契数-CSDN博客

    2024年02月19日
    浏览(35)
  • 代码随想录 Leetcode18. 四数之和

            不行了,今天做了太多n数之和要吐了,太恶心了,一堆剪枝,去重太恶心人了。最后还是照着卡哥的改

    2024年01月17日
    浏览(73)
  • 代码随想录 LeetCode数组篇 二分查找

    # (简单)704. 二分查找 题目链接 代码随想录 - 二分查找思路 二分查找,思路很简单,但是在while循环left和right的比较是写=还是,还有right=mid还是right=mid-1容易混淆 需要想清楚对区间的定义,是[left,right],还是[left,right) (版本一,左闭右闭版本) (版本二,左闭右开) 题目

    2024年02月02日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包