代码随想录一刷总结
数组
数组篇5题
数组理论基础
二分法
循环不变量原则,坚持对区间的定义,确定好边界的范围
双指针法
通过一个快指针和慢指针在一个for循环下完成两个for循环的工作
滑动窗口
滑动窗口也算是一种双指针
链表
链表篇7题
链表理论基础
虚拟头节点
有了虚拟头节点就对链表的增删操作统一了
链表的基本操作
也用到了虚拟头节点,方便增删改的操作
反转链表
递归法和迭代法(双指针)
两两交换链表中的节点
虚拟头节点
删除倒数第N个节点
虚拟头节点+快慢指针
链表相交
双指针
环形链表
找环,但要设计一些数学证明
哈希表
哈希表8题
哈希表理论基础
什么时候用哈希表?给你一个元素判断在这个集合里是否出现过
一般来说哈希表都是用来快速判断一个元素是否出现集合里。
数组作为哈希表
数组大小是受限的
Set作为哈希表
数组大小没有限制,避免浪费就用Set做映射了
Map作为哈希表
map是一种<key, value>
的结构,本题可以用key保存数值,用value在保存数值所在的下标。所以使用map最为合适
字符串
字符串7题
双指针法
字符串的题型常客
剑指Offer 05.替换空格
反转系列
剑指Offer 58-II.左旋转字符串
KMP
KMP的主要思想是当出现字符串不匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头再去做匹配了。
栈与队列
栈与队列7题
栈与队列理论基础
栈的经典问题
括号匹配问题
字符串去重问题
逆波兰表达式问题
队列的经典问题
滑动窗口最大值问题
单调队列
求前 K 个高频元素
优先级队列
二叉树
二叉树31题
基本都是可递归可迭代
递归法三部曲:
- 递归函数的参数和返回值
- 终止条件
- 单层递归的逻辑
迭代法
二叉树理论基础
二叉树遍历方式
深度优先遍历:
三种排序都可以通过递归实现
前序后续可以通过递归、通过栈实现递归解决,但中序遍历用栈实现递归的话要做标记
广度优先遍历:
通过队列模拟
二叉树的属性
递归:后序,比较的是根节点的左子树与右子树是不是相互翻转
迭代:使用队列/栈将两个节点顺序放入容器中进行比较
递归:后序,求根节点最大高度就是最大深度,通过递归函数的返回值做计算树的高度
迭代:层序遍历
递归:后序,求根节点最小高度就是最小深度,注意最小深度的定义
迭代:层序遍历
递归:后序,通过递归函数的返回值计算节点数量
迭代:层序遍历
递归:后序,注意后序求高度和前序求深度,递归过程判断高度差
迭代:效率很低,不推荐
递归:前序,方便让父节点指向子节点,涉及回溯处理根节点到叶子的所有路径
迭代:一个栈模拟递归,一个栈来存放对应的遍历路径
递归:后序,必须三层约束条件,才能判断是否是左叶子。
迭代:直接模拟后序遍历
递归:顺序无所谓,优先左孩子搜索,同时找深度最大的叶子节点。
迭代:层序遍历找最后一行最左边
递归:顺序无所谓,递归函数返回值为bool类型是为了搜索一条边,没有返回值是搜索整棵树。
迭代:栈里元素不仅要记录节点指针,还要记录从头结点到该节点的路径数值总和
二叉树的修改与构造
递归:前序,交换左右孩子
迭代:直接模拟前序遍历
递归:前序,重点在于找分割点,分左右区间构造
迭代:比较复杂,意义不大
递归:前序,分割点为数组最大值,分左右区间构造
迭代:比较复杂,意义不大
递归:前序,同时操作两个树的节点,注意合并的规则
迭代:使用队列,类似层序遍历
二叉搜索树的属性
递归:二叉搜索树的递归是有方向的
迭代:因为有方向,所以迭代法很简单
递归:中序,相当于变成了判断一个序列是不是递增的
迭代:模拟中序,逻辑相同
递归:中序,双指针操作
迭代:模拟中序,逻辑相同
递归:中序,清空结果集的技巧,遍历一遍便可求众数集合
递归:中序,双指针操作累加
迭代:模拟中序,逻辑相同
二叉树公共祖先问题
递归:后序,回溯,找到左子树出现目标值,右子树节点目标值的节点。
迭代:不适合模拟回溯
递归:顺序无所谓,如果节点的数值在目标区间就是最近公共祖先
迭代:按序遍历
二叉搜索树的修改与构造
递归:顺序无所谓,通过递归函数返回值添加节点
迭代:按序遍历,需要记录插入父节点,这样才能做插入操作
递归:前序,想清楚删除非叶子节点的情况
迭代:有序遍历,较复杂
递归:前序,通过递归函数返回值删除节点
迭代:有序遍历,较复杂
递归:前序,数组中间节点分割
迭代:较复杂,通过三个队列来模拟
回溯算法
回溯算法12题
回溯三部曲:
- 回溯函数的参数和返回值
- 终止条件
- 单层搜索的逻辑
回溯算法理论基础
回溯是递归的副产品,只要有递归就会有回溯
回溯法就是暴力搜索,并不是什么高效的算法,最多再剪枝一下
所有回溯问题都可以抽象成树形结构
组合问题
组合问题
for循环横向遍历,递归纵向遍历,回溯不断调整结果集
剪枝精髓是:for循环在寻找起点的时候要有一个范围,如果这个起点到集合终止之间的元素已经不够题目要求的k个元素了,就没有必要搜索了
在for循环上做剪枝操作是回溯法剪枝的常见套路
组合总和
组合总和(一)
已选元素总和如果已经大于n(题中要求的和)了,那么往后遍历就没有意义了,直接剪掉
组合总和(二)
如果是多个集合取组合,各个集合之间相互不影响,那么就不用startIndex
本题还需要startIndex来控制for循环的起始位置
组合总和(三)
集合元素会有重复,但要求解集不能包含重复的组合。“树枝去重”和“树层去重”
多个集合求组合
切割问题
用求解组合问题的思路来解决 切割问题本题就成功一大半了
但后续如何模拟切割线,如何终止,如何截取子串,其实都不好想,最后判断回文算是最简单的了
复原IP地址
子集问题
子集问题(一)
在树形结构中子集问题是要收集所有节点的结果,而组合问题是收集叶子节点的结果
子集问题(二)
多了去重
递增子序列
和子集很像
排列问题
排列问题(一)
不同之处:
- 每层都是从0开始搜索而不是startIndex
- 需要used数组记录path里都放了哪些元素了
排列问题(二)
去重,“树层去重”和“树枝去重”
贪心算法
贪心算法16题
贪心理论基础
找出局部最优并可以推出全局最优
贪心简单题
贪心中等题
贪心解决股票问题
两个维度权衡问题
贪心解决区间问题
其他难题
动态规划
动态规划38题
动态规划五部曲:
- 确定dp数组(dp table)以及下标的含义
- 确定递推公式
- dp数组如何初始化
- 确定遍历顺序
- 举例推导dp数组
动态规划基础
背包问题
01背包理论基础
01背包理论基础(滚动数组)
完全背包理论基础
多重背包理论基础
打家劫舍
买卖股票系列
子序列系列
单调栈
单调栈5题
结语:
一路走来,我是没想到自己真的坚持下来了哈哈哈,首先Carl哥讲的是真的好,很通透且清晰,从最开始的数组,到最后的单调栈,循序渐进,层层递进,一环扣一环,有些难题本来就不会做,没有前面的铺垫那就更加不会了,Carl哥用心了!
其实自己也不好说完全掌握了这一路走来做的所有题,毕竟本来几乎没什么算法基础,总结完以后,以后估计都得二刷三刷什么的,算法就是这样,练得少就不行。
数组的二分、双指针,链表的虚拟头节点、双指针,哈希表的数组、Set、Map,字符串的双指针、KMP,栈与队列的经典问题,二叉树的递归三部曲、遍历、属性、构造以及搜索树,回溯算法三部曲、组合、排列,贪心算法的局部推导全局,动态规划的五部曲,以及最后的单调栈收尾,这一切的学到的东西都让我收获满满,不少以前从来没听说过的,经过这60天的算法训练,让我一直不断提升,比前一天的自己更好,但不是说跟着Carl哥练完这60天,就变得无敌了,自己不努力改变,没人能替你成长。往后每天还是得不断坚持刷题,坚持巩固,也不祈求以后进个什么大厂,只要坚持以后,能达到我自己所能达到的级别即可。
problems/next-greater-element-ii/)
结语:
一路走来,我是没想到自己真的坚持下来了哈哈哈,首先Carl哥讲的是真的好,很通透且清晰,从最开始的数组,到最后的单调栈,循序渐进,层层递进,一环扣一环,有些难题本来就不会做,没有前面的铺垫那就更加不会了,Carl哥用心了!
其实自己也不好说完全掌握了这一路走来做的所有题,毕竟本来几乎没什么算法基础,总结完以后,以后估计都得二刷三刷什么的,算法就是这样,练得少就不行。
数组的二分、双指针,链表的虚拟头节点、双指针,哈希表的数组、Set、Map,字符串的双指针、KMP,栈与队列的经典问题,二叉树的递归三部曲、遍历、属性、构造以及搜索树,回溯算法三部曲、组合、排列,贪心算法的局部推导全局,动态规划的五部曲,以及最后的单调栈收尾,这一切的学到的东西都让我收获满满,不少以前从来没听说过的,经过这60天的算法训练,让我一直不断提升,比前一天的自己更好,但不是说跟着Carl哥练完这60天,就变得无敌了,自己不努力改变,没人能替你成长。往后每天还是得不断坚持刷题,坚持巩固,也不祈求以后进个什么大厂,只要坚持以后,能达到我自己所能达到的级别即可。
看似不起波澜的日复一日,一定会在某一天,让你看到坚持的意义。