算法模板与专题整理
文章平均质量分 88
整理了一些专题,和相关模板
大磕学家ZYX
这个作者很懒,什么都没留下…
展开
-
专题:链表常考题目汇总
指针存放地址ListNode*是一个指针,它存储的是链表节点的地址。删除节点在删除链表中的一个节点前,需要有一个临时指针变量存储该节点的地址。这是因为在更改前一个节点的next指针,跳过当前节点后,如果没有这个临时指针,你将无法访问到这个节点,也就无法释放它占用的内存。释放内存一旦链表中的节点被跳过,且没有其他指针指向它,你就需要通过临时指针来释放该节点的内存,防止内存泄漏。保持链表连贯性: 使用临时指针,在逻辑上移除链表节点之前保存节点地址可以在物理上移除该节点时保持链表的连贯性。原创 2023-10-20 23:01:50 · 836 阅读 · 0 评论 -
算法专题:前缀和
首先思路就是运用前缀和,单独开一个x数组遍历所有的nums[i],满足条件计数为1,不满足条件计数为0。求子数组中某一段数字的元素和,只需要转换成两个数字的差值就可以了。这种写法因为子数组两边都不定,会超时,时间复杂度是O(n^2)。遍历完了数组之后一定会收集所有的相加=目标和的两数组合。两数之和的优化方法是,遍历到nums[i]的时候,先看看。)子区间和 (即 3 + 4 + 5),我们可以使用。**注意:**子数组是数组中的一个连续非空的元素序列。以整数形式表示并返回趣味子数组的数目。原创 2023-09-07 22:39:40 · 572 阅读 · 0 评论 -
算法专题:子序列系列2(回文,区间DP)
判断字符串S是否是回文,如果我们知道 s[1],s[2],s[3] 这个子串是回文的,那么只需要比较 s[0]和s[4]这两个元素是否相同,如果相同的话,这个字符串s 就是回文串。如果做了很多这种子序列相关的DP题目,在定义dp数组的时候 很自然就会想题目求什么,我们就如何定义dp数组。遍历顺序同上一题,i是倒序遍历,j是正序遍历,且j>i(本题不是j>=i了,因为长度累加+2)本题是不连续的,但是DP数组依然是按照回文系列定义[i,j]区间的方式来定义。的状态,因此i的状态要通过i+1来推出。原创 2023-08-01 22:54:21 · 387 阅读 · 0 评论 -
算法专题:子序列系列1
关于两个序列之间的问题,为了简化初始化,DP数组的定义一般为:以下标i - 1为结尾的A,和以下标j - 1为结尾的B待求量为dp[i][j]。也就是说会存在错位,i和j的范围是。这个错位操作的目的主要是为了简化初始化DAY52:动态规划(十七)子序列问题:最长递增子序列+最长连续递增序列+最长重复子数组_大磕学家ZYX的博客-CSDN博客如果要求的子序列是连续的子序列,那么DP数组含义一定是“以nums[i]为结尾的序列,待求量为dp[i]”如果不连续但是i+1需要用到i的状态进行判断,例如。原创 2023-08-01 22:53:13 · 248 阅读 · 0 评论 -
DAY52:动态规划(十七)子序列问题:最长递增子序列+最长连续递增序列+最长重复子数组
本题的最大值并不在dp数组末尾,因为每个数据都可能比前面的数字要小。最大长度可能是dp数组中间位置的dp[i],所以需要建个result存最大值。初始化要注意,本题每个以i为结尾的递增子序列,长度最小是1而不是0!本题难点在于,比较两个数组,得到重复且连续的最长子数组,用一维的DP数组无法同时表示两个数组的状态。我们需要用一个二维的矩阵来比较两个数组的所有状态。dp[0][j]和dp[i][0]的情况都需要单独初始化。原创 2023-07-26 15:27:37 · 770 阅读 · 0 评论 -
算法专题:投票法
这两个问题之间的主要区别在于正在寻找的元素的数量。在查找主要元素的问题中,出现次数超过了n/2的只可能有一个元素。在这种情况下,当count变为0时可以安全地开始考虑一个新的候选元素,因为不可能有两个元素都出现次数超过n/2。所以当count为0时,可以肯定之前的元素不可能是主要元素,所以重新设置一个候选主要元素是合理的。然而,当寻找的是出现次数超过n/3的元素时,一个数组有可能存在两个这样的元素。所以,不能直接在count为0时就更改候选元素,必须先判断新元素是不是==num1/==num2!原创 2023-07-20 17:35:57 · 341 阅读 · 0 评论 -
DAY49:动态规划:多重背包理论基础
多重背包在面试中基本不会出现,力扣上也没有对应的题目,对多重背包的掌握程度知道它是一种01背包,并能在01背包的基础上写出对应代码就可以了。原创 2023-07-20 00:52:43 · 55 阅读 · 0 评论 -
DAY47:动态规划(十)零钱兑换Ⅱ+组合总和Ⅳ(完全背包求方案总数类型,排列+组合)
完全背包问题,在求装满背包有几种方案的时候,认清遍历顺序是非常关键的。如果求所有装满背包方案的组合数,就是外层for循环遍历物品,内层for遍历背包。如果求所有方案的排列数,就是外层for遍历背包,内层for循环遍历物品。01背包因为物品和背包遍历顺序不能颠倒,所以并不存在排列数和组合数的问题。如果面试问到for嵌套顺序颠倒计算排列数和组合数的原理,可以这么回答:物品在外的话,必须考虑完 i 的所有情况之后再考虑 i + 1,所以去掉了他们的排列关系;而。原创 2023-07-14 20:51:33 · 303 阅读 · 0 评论 -
DAY47:动态规划(九)完全背包理论基础
注意,全文说的都是对于纯完全背包问题其for循环的先后循环是可以颠倒的!但如果题目稍稍有点变化,就会体现在遍历顺序上。如果问装满背包有几种方式的话,那么两个for循环的先后顺序就有很大区别了。如果我们先遍历背包后遍历物品,得到的就是方案的排列数;先遍历物品再遍历背包,得到的就是方案组合数。518.零钱兑换Ⅱ377.组合总和Ⅳ中进行进一步的理解。【总结】用树形图和剪枝操作理解完全背包问题中组合数和排列数问题_先遍历物品后遍历背包是组合数_Calculus2022的博客-CSDN博客。原创 2023-07-14 20:47:47 · 161 阅读 · 0 评论 -
DAY46:动态规划(八)01背包应用2:一和零(二维容量01背包)
01背包问题纯 0 - 1 背包 是求给定背包容量,背包的最大价值是多少。分割等和子集 是求给定背包容量,能不能装满这个背包。最后一块石头的重量 II 是求给定背包容量,尽可能装,最多能装多少。目标和 是求给定背包容量,装满背包一共有多少种方案。474.一和零 是求给定背包容量,装满背包最多有多少个物品。(本题属于二维容量的背包)原创 2023-07-14 15:34:02 · 124 阅读 · 0 评论 -
DAY46:动态规划(七)01背包应用:分割等和子集+最后一块石头重量Ⅱ+目标和
这道题目就是一道01背包应用类的题目,需要我们拆解题目,然后套入01背包的场景。01背包相对于本题,主要要理解,题目中物品是nums[i],重量是nums[i],价值也是nums[i],背包体积是sum/2。第一种写法是重量=价值的写法,相对来说好理解一些。需要注意的一点就是重量=价值,那么dp[j]代表的最大价值,一定<=j(最大重量),因为背包问题的大前提就是,放入背包的所有物品最大重量一定<=背包容量。有一堆石头,用整数数组 stones 表示。其中stones[i]表示第 i 块石头的重量。原创 2023-07-14 03:33:36 · 217 阅读 · 0 评论 -
DAY45:动态规划(六)背包问题优化:一维DP解决01背包问题
背包最大重量为4。物品重量和价值为:问背包能背的物品最大价值是多少?在我们使用二维DP数组的时候,递推公式是.如果要降为一维DP数组,就是用来表示递推。这里用j是为了j的含义和二维DP数组保持一致,下标含义都是背包的容量。原始的二维DP状态转移方程是:。这个方程意味着,对于第i个物品和当前背包容量j,我们要么选择放入这个物品,要么不放。如果放入这个物品,就需要看在容量为时,放入前i-1个物品的最大价值(也就是),如果不放入这个物品,就是。然后取这两者之间的最大值。二维背包DP数组情况示例如下图所示。我们原创 2023-07-12 20:09:05 · 482 阅读 · 0 评论 -
DAY45:动态规划(五)背包问题:01背包理论基础+二维DP解决01背包问题
对于每一种物品(纵轴上的索引i),对于每一个背包大小(横轴上的索引j),都计算出当前背包大小能存放物品的最大价值。如果当前背包的容量无法装下物品i,那么dp[i][j]的值就等于dp[i-1][j],否则,需要在“不放入物品i”和“放入物品i”这两种选择中选取价值最大的,即。这样,遍历到指定背包大小的时候,得到的就是当前背包可以装下物品的最大价值。所以说,这个DP递推公式对于每一个背包数值都适用。我们需要时刻注意,遍历到每一个物品的时候,dp[i][j]原创 2023-07-12 20:03:58 · 267 阅读 · 0 评论 -
算法专题整理:滑动窗口
因此result会在每一个right遍历的时候进行累加,得到**[left,right]窗口内所有大小的数组个数**。本题特定条件并不复杂,是求和的条件,并不需要单独写函数。只要满足特定条件,就可以进行滑动。特定条件是,对于子数组中的任意两个元素,他们的绝对值差不能超过 2。例如[1,2,3],所有以right=3为右端点的子数组,就是。,如果左端点的移动条件不明或者比较复杂,就不适合用滑动窗口。本题是很经典的滑动窗口题目,选取特定条件下的连续子数组。的数组个数,加上是遍历right,因此我们的策略是。原创 2023-07-03 20:22:48 · 638 阅读 · 0 评论 -
回溯注意点:回溯时间复杂度的计算与剪枝操作
不剪枝的版本会尝试所有的可能组合,直到得到长度为k的组合。然而,对于一些情况,当我们已经选择了足够多的元素,使得剩余的元素不足以填满长度为k的组合时,我们仍然会继续尝试,这其实是无效的。在这种情况下,我们仍然可以使用公式来大致评估时间复杂度,但需要注意,这只是一个大概的评估,因为在某些路径中,可能由于和超过了目标值或者元素数量已满,提前结束了搜索。在电话号码的字母组合问题中,我们需要为输入的每一个数字选择一个字母,每一个数字都有几个可能的字母,我们需要尝试所有的可能选择,以生成所有可能的组合。原创 2023-06-25 02:33:34 · 1538 阅读 · 2 评论 -
常用模板2:归并排序
在这个例子中,我们首先定义了一个整数数组arr,然后使用sizeof操作符计算数组的长度。最后,我们遍历数组并打印排序后的结果,然后删除临时数组。它将一个大问题(排序整个数组)分解为两个小问题(排序两个子数组),然后将这两个小问题的解(两个排序好的子数组)合并为大问题的解(整个排序好的数组)。它首先检查子数组的长度是否大于1,如果l >= r,则直接返回,因为长度为1或0的数组已经排序好了。然后,函数找到子数组的中点mid,并递归地对左半部分(l到mid)和右半部分(mid+1到r)进行排序。原创 2023-06-14 01:15:59 · 352 阅读 · 0 评论 -
常用模板1:快速排序
这两步操作的目标是找到数组中的一对元素,其中左边的元素大于基准元素,右边的元素小于基准元素,然后交换这对元素。这样,在每次循环结束时,都能保证基准元素左边的元素都小于或等于基准元素,右边的元素都大于或等于基准元素,从而完成了一轮的分区操作。这次从右边(即较大的索引)开始遍历,只要遇到的元素大于基准元素,就将索引j向左移动一位,即j–。一旦找到一个小于等于基准元素的元素,就跳出循环。从左边(即较小的索引)开始遍历,只要遇到的元素小于基准元素,就将索引i向右移动一位,即i++。原创 2023-06-14 01:09:46 · 221 阅读 · 0 评论 -
堆(优先级队列)的比较运算与快速排序默认cmp函数的区别
在建堆过程中,我们需要维护堆的性质。当我们说 "左大于右就会建立小顶堆,右大于左反而建立大顶堆"时,实际上我们是在。(优先级队列的定义正好反过来了。估计是底层实现上优先队列队首指向后面,队尾指向最前面的缘故)这就是为什么在建堆过程中,“左大于右就会建立小顶堆,右大于左反而建立大顶堆”。 在快速排序中,我们确实可以通过更改比较函数。但在堆排序中,情况稍有不同。例如,sort函数里面。答:这个问题主要涉及到。原创 2023-06-12 21:57:27 · 597 阅读 · 0 评论 -
螺旋矩阵题目的两种解法及注意点
创建了一个名为 ans 的 n x n 的二维整数数组,所有元素都初始化为 0。数组的定义对应了在二维矩阵中向四个方向(右,下,左,上)移动的坐标变化规则。这四个方向是按照螺旋矩阵的生成规则设定的。,这表示初始的移动方向为向右。**当在矩阵的边界或者已经填充的单元格需要改变方向时,通过。时,我们的代码可能会试图访问数组的越界索引,从而可能导致运行时错误。是否超出了矩阵的边界时,我们需要比较它们是否等于或者大于。通过这种方式,可以便捷地控制在二维矩阵中的移动方向。,该公式中t从0开始取值,公式的结果是。原创 2023-05-12 15:28:43 · 128 阅读 · 0 评论 -
双指针法实现快速排序
如果子数组已经足够小(例如,只包含一个元素),那么这个子数组已经是排序好的。 快速排序是一种非常高效的排序算法,它的基本思想是“分而治之”。也就是说,如果我们需要对一个数组进行排序,可以。相遇的时候,程序可能会交换一个元素与自身,虽然这不会影响排序的结果,但是这是一个不必要的操作。两个指针会分别从数组的两端开始搜索,直到找到需要交换的元素。相遇时,我们需要确定这个位置在下一次递归中属于哪个子数组。及其左边的元素应该属于左边的子数组,而。,所以这两个表达式的效果是一样的。,这样在循环的第一次迭代中,原创 2023-05-11 16:23:39 · 695 阅读 · 0 评论