代码随想录算法训练营总结篇

通过本次为期两个月的算法训练使自己对于算法中一些名词有了更加深刻的理解。接下来我将按照这段时间的算法题目做一个总结。

在进入算法训练之前首先应对时间复杂度和空间复杂度有一个认识,我们在完成一道代码题后,对其进行优化的前提是可以从目前已完成的代码分析,做出优化。而这其中递归算法的分析是重要一环

递归算法时间复杂度 = 递归的次数 * 每次递归中的操作次数

递归算法的空间复杂度 = 每次递归的空间复杂度 * 递归深度

接下来进入到了算法最开始的题目,在数组题目中的螺旋矩阵是最令我印象深刻的,这道题让我对于循环不变量有了直观的理解,在数字填充过程中一定要始终保持一种原则进行填充,否则会更加混乱。

在链表这一章节中,虚拟头节点给解题带来了极大的帮助,借助虚拟头节点,可以不必再对真正的头结点进行另行讨论,简化了代码。环形链表的出现是借助数学理论进行结果的判断,如果使用数学推理对于解题有很大阻力。

在哈希表中常见的三种哈希结构(数组,set(集合),map(映射))的定义及应用有了详细的理解,一般来说哈希表都是用来快速判断一个元素是否出现集合里。对于哈希表,要知道哈希函数哈希碰撞在哈希表中的作用,哈希函数是把传入的key映射到符号表的索引上。哈希碰撞处理有多个key映射到相同索引上时的情景,处理碰撞的普遍方式是拉链法和线性探测法。

在C++中,set 和 map 分别提供以下三种数据结构,其底层实现以及优劣如下表所示:

集合底层实现是否有序数值是否可以重复能否更改数值查询效率增删效率
std::set红黑树有序O(log n)O(log n)
std::multiset红黑树有序O(logn)O(logn)
std::unordered_set哈希表无序O(1)O(1)

std::unordered_set底层实现为哈希表,std::set 和std::multiset 的底层实现是红黑树,红黑树是一种平衡二叉搜索树,所以key值是有序的,但key不可以修改,改动key值会导致整棵树的错乱,所以只能删除和增加。

映射底层实现是否有序数值是否可以重复能否更改数值查询效率增删效率
std::map红黑树key有序key不可重复key不可修改O(logn)O(logn)
std::multimap红黑树key有序key可重复key不可修改O(log n)O(log n)
std::unordered_map哈希表key无序key不可重复key不可修改O(1)O(1)

std::unordered_map 底层实现为哈希表,std::map 和std::multimap 的底层实现是红黑树。同理,std::map 和std::multimap 的key也是有序的。

当我们要使用集合来解决哈希问题的时候,优先使用unordered_set,因为它的查询和增删效率是最优的,如果需要集合是有序的,那么就用set,如果要求不仅有序还要有重复数据的话,那么就用multiset。

map 是一个key value 的数据结构,map中,对key是有限制,对value没有限制的,因为key的存储方式使用红黑树实现的。

在字符串章节中KMP的主要思想是当出现字符串不匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头再去做匹配了。

前缀表:起始位置到下标i之前(包括i)的子串中,有多大长度的相同前缀后缀。

那么使用KMP可以解决两类经典问题:匹配问题;重复子串问题

接下来是双指针法,双指针法是应用比较广的一个算法,从数组移除重复元素,到链表中的翻转链表,到哈希表中的三数之和(四数之和)问题,到字符串替换单词,均有涉及,双指针法的出现可以极大帮助我们解题,提高时间复杂度。

在栈和队列章节中,我们首先要对其定义有了解,从一开始的用栈实现队列,用队列实现栈来掌握的栈与队列的基本操作。接着,通过括号匹配问题、字符串去重问题、逆波兰表达式问题来系统讲解了栈在系统中的应用,以及使用技巧。通过求滑动窗口最大值,以及前K个高频元素介绍了两种队列:单调队列和优先级队列,这是特殊场景解决问题的利器,是一定要掌握的。

在二叉树章节,从遍历方式到二叉树的属性,从二叉树的修改与构造到二叉搜索树的属性,再到二叉公共祖先问题,二叉搜索树的修改与构造。二叉树我们要掌握二叉树的种类,遍历方式,存储方式,定义,在掌握这些的基础上,有助于解题的规范化。

  • 涉及到二叉树的构造,无论普通二叉树还是二叉搜索树一定前序,都是先构造中节点。

  • 求普通二叉树的属性,一般是后序,一般要通过递归函数的返回值做计算。

  • 求二叉搜索树的属性,一定是中序了,不然就浪费了有序性了。

在回溯法章节我们了解到,其实回溯法并不是高效的算法,回溯法的本质其实是穷举。

回溯法,一般可以解决如下几种问题:

  • 组合问题:N个数里面按一定规则找出k个数的集合
  • 切割问题:一个字符串按一定规则有几种切割方式
  • 子集问题:一个N个数的集合里有多少符合条件的子集
  • 排列问题:N个数按一定规则全排列,有几种排列方式
  • 棋盘问题:N皇后,解数独等等

解回溯算法的题遵照回溯三部曲

1、回溯函数模板返回值以及参数

2、回溯函数终止条件

3、回溯搜索的遍历过程

接下来是贪心算法章节,贪心的本质是选择每一阶段的局部最优,从而达到全局最优。贪心算法本身并没有什么清晰的定义,对于什么时候用贪心,取决于我们是否可以从局部最优达到全局最优。

贪心算法一般分为如下四步:

  • 将问题分解为若干个子问题
  • 找出适合的贪心策略
  • 求解每一个子问题的最优解
  • 将局部最优解堆叠成全局最优解

接下来是动态规划章节,动态规划,英文:Dynamic Programming,简称DP,如果某一问题有很多重叠子问题,使用动态规划是最有效的。所以动态规划中每一个状态一定是由上一个状态推导出来的,这一点就区分于贪心,贪心没有状态推导,而是从局部直接选最优的。

对于动态规划问题,需要掌握动规五部曲

  1. 确定dp数组(dp table)以及下标的含义
  2. 确定递推公式
  3. dp数组如何初始化
  4. 确定遍历顺序
  5. 举例推导dp数组

动态规划题目最重要的一步便是举例推导dp数组,通过举例推导可以证实我们的思路是否正确严谨。

在单调栈章节中,单调栈的使用场景通常是一维数组,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置,此时就要想到可以用单调栈了。时间复杂度为O(n)。单调栈的本质是空间换时间,因为在遍历的过程中需要用一个栈来记录右边第一个比当前元素高的元素,优点是整个数组只需要遍历一次。

在使用单调栈的时候首先要明确如下几点:

1、单调栈里存放的元素是什么?

单调栈里只需要存放元素的下标i就可以了,如果需要使用对应的元素,直接T[i]就可以获取。

2、单调栈里元素是递增呢? 还是递减呢?

如果求一个元素右边第一个更大元素,单调栈就是递增的,如果求一个元素右边第一个更小元素,单调栈就是递减的。

同时注意使用单调栈主要有三个判断条件。

  • 当前遍历的元素T[i]小于栈顶元素T[st.top()]的情况
  • 当前遍历的元素T[i]等于栈顶元素T[st.top()]的情况
  • 当前遍历的元素T[i]大于栈顶元素T[st.top()]的情况

通过这两个月的学习,我最大的感受是每天解代码题是一件十分有成就感的事,本人目前大四,每天做的事情就是搞毕设,写论文,找工作,十分枯燥,本来之前考研以后,想靠刷题来提升自己进复试的,奈何成绩不足以进复试,只能找工作了,但是代码随想录是我每天开始新的一天的第一件事,通过代码随想录使我对于算法的了解更深入了,最起码以后当我碰到类似问题时,我不会说“我之前了解过,我去网上再深入了解一下”等无能回答。 

最后感谢一下卡哥及卡哥助手_围城,他们每天在群里耐心解答各种问题,很负责,虽然我个人提问较少,但是每天看到群里面的各种疑惑解答,自己对于该问题的答案也就更明了了。

代码随想录算法训练营是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练营中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练营还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练营中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14天的训练营中,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文章和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练营还提供了每日的讨论知识点,例如在第15天的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16天的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法代码。 总之,代码随想录算法训练营是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练营每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值