![](https://img-blog.csdnimg.cn/20190918140213434.png?x-oss-process=image/resize,m_fixed,h_224,w_224)
数据结构与算法刷题
文章平均质量分 62
数据结构与算法刷题
辰阳星宇
这个作者很懒,什么都没留下…
展开
-
【算法刷题】树和二叉树题型及方法归纳
二叉树是有左、右孩子的树,存储方式有顺序存储和链式存储。原创 2023-05-24 18:07:39 · 580 阅读 · 0 评论 -
203、【栈与队列】leetcode ——剑指 Offer II 040. 矩阵中最大的矩形 / 85. 最大矩形:暴力+单调栈(C++/Pyhont版本)
C++Python参考文章:矩阵中最大的矩形原创 2023-04-23 22:56:35 · 402 阅读 · 0 评论 -
202、【数组】leetcode ——2588. 统计美丽子数组数目(C++版本)
使用一个哈希表,key为前缀和,value为具有该前缀和的个数。因为是要找到所有的满足异或后为0的子区间,因此,需要的就是对相同的前缀和进行两两配对,便计算出了所有情况。规定前缀和为异或运算后的前缀和,只要找到前缀和相同的两个位置,此时这两个位置之间的区间,异或后就一定为0。因此,问题就转化为了找到一个一个区间内,所有的数进行异或操作后数值变为0。本题的难点在于对于题意的解析与思路的转化。(异或运算:对相同为0,相异为1,0与任何数计算该数数值保持不变),而前缀和是处理子区间内数值的常用方式。原创 2023-03-13 17:20:57 · 463 阅读 · 0 评论 -
201、【数组】leetcode ——面试题 17.05. 字母与数字(C++版本)
参考文章:字母与数字原创 2023-03-13 13:01:30 · 264 阅读 · 0 评论 -
200、【数组】leetcode ——6316. 重排数组以得到最大前缀分数(C++版本)
排序找前缀和为正数的个数原创 2023-03-12 20:27:05 · 89 阅读 · 0 评论 -
199、【哈希表】leetcode ——6315. 统计范围内的元音字符串数(C++版本)
哈希表+字符串原创 2023-03-12 16:10:15 · 112 阅读 · 0 评论 -
198、【动态规划】leetcode ——983. 最低票价:记忆化搜索(C++版本)
(1)dp[i]含义: 第i天时,所需要的最低消费。(2)递推公式: dp[i]=min(dp[i−1]+cost[0],dp[i−7]+cost[1],dp[i−30]+cost[2])dp[i] = min(dp[i - 1] + cost[0], dp[i - 7] + cost[1], dp[i - 30] + cost[2])dp[i]=min(dp[i−1]+cost[0],dp[i−7]+cost[1],dp[i−30]+cost[2]),从上述三种情况中反推出来那种情况到达第i天时开销最小。原创 2023-03-11 22:19:51 · 296 阅读 · 0 评论 -
197、【动态规划】AcWing —— 901. 滑雪(C++版本)
整体思路就是依次进行递归遍历,从不同的起始位置出发找到一条最长区域路径。每次探寻时,从上下左右四个方向寻找,最终找到一条最长路径。,意为在已有的结果中和向上下左右某一个方向继续探索后,找到一个最大区域长度结果。dp[i][j] = 1,每个自身代表一个长度。位于(i, j)时,具有的最长区域路径长度。原创 2023-03-11 11:38:08 · 535 阅读 · 0 评论 -
196、【动态规划】AcWing —— 285. 没有上司的舞会(C++版本)
题目是要构造一个树形关系,在选择时,有直接上下级关系的不能选,但是对于有间接上下级关系的和非上下级关系的都可以选。dp[i][0]:不选节点i时,具有的最大快乐数。dp[i][1]:选节点i时,具有的最大快乐数。dp[i][1] = happy[i],当选择孩子节点时,初始时候为自身的快乐数值。,意为在不选择i节点的情况下,选择孩子节点和不选择孩子节点时候找到一个最大值。(其中j为i的孩子节点),意为选择当前节点的情况下加上不选择孩子节点的情况;后序遍历,从左到右,从下到上,将低层结果传递给上一层。原创 2023-03-10 21:49:37 · 417 阅读 · 1 评论 -
195、【动态规划】AcWing —— 91. 最短Hamilton路径(C++版本)
到达点j并且状态为i时,具有的最短路径长度,其中状态j用状态压缩二进制的方式表示。j中从0-n-1位分别对应点0到点n-1,j中某一位的值为1时代表走入此点,值为0时代表不走入此点。因为要求的最短路径需要在之前的点已经添加的基础上进行更新,先遍历状态再遍历点,可以得知在状态i(某些点添加某些点未添加)时,点j到达起始点0的最短路径。dp[1][0] = 0,表示走入初始点0时,此时的距离出发点的距离为0。加减法的优先级 > 位运算的优先级,需要对位元算带括号。)时,从第k个点到达第j个点所需要的路径长度。原创 2023-03-09 11:27:05 · 449 阅读 · 0 评论 -
194、【动态规划】AcWing —— 291. 蒙德里安的梦想:状压dp详细解析(C++版本)
答:因为我们要求的是从第j-1列转化到第j列是的所有合法状态,因此先for循环j时,代表我们的目标列j此时的状态,此时第j列的空格数不为偶数个,而是奇数个,就会导致1×2的长方体一定不能填充满这一列,因此此状体不合法。,代表从当前位置横着新摆放一个长方体(此时第j+1列、第i行,会由第i列伸出一个长方体)。此时由于第j-1列新横放的方块和第j列新横放的方块出现重叠,因此此状态不合法。,表示从第i-1列到达第i列,可转化为状态j的所有合法状态求和。第i列处,状态为j时,合法的方案数。因此,本问题就转化为了,原创 2023-03-08 12:31:32 · 628 阅读 · 2 评论 -
193、【栈与队列】leetcode ——面试题 16.26. 计算器(C++版本)
参考文章:双栈算法、面试题 16.26. 计算器(C++ 「栈+辅助栈」【图解】)原创 2023-03-06 21:07:12 · 97 阅读 · 0 评论 -
192、【动态规划】leetcode ——64. 最小路径和:回溯法+动态规划(C++版本)
分别向右或下进行探查此方式会超时。原创 2023-03-05 21:02:26 · 393 阅读 · 1 评论 -
191、【动态规划】AcWing —— 900. 整数划分:完全背包解法+加减1解法(C++版本)
例如:组合成3的方案可以为2、1和1、1、1,当我们想要得到组合成4的方案,那么就可以分别从2、1和1、1、1演化过来,就是2、1、1和1、1、1、1,此时3中这一部分含有最小值为1的方案个数与4中这一部分含有最小值为1的方案个数其实是相同的。例如:组合成3的方案可以为2、1和1、1、1,当我们想要得到组合成4的方案,那么就可以分别从2、1和1、1、1演化过来,就是2、1、1和1、1、1、1,此时3中这一部分含有最小值为1的方案个数与4中这一部分含有最小值为1的方案个数其实是相同的。从左到右,从上到下。原创 2023-03-05 12:37:25 · 435 阅读 · 0 评论 -
190、【动态规划】AcWing ——282. 石子合并(C++版本)
其中(i < k < j),k为区间的分割点,x为下标i到j之间的总代价和。因为题中要求的就是每次加上合并后的结果,因此加上这段区间之和。dp[i][j] = MAX(i ≠ j),因为求最小值,所以让其取最大。dp[i][i] = 0,区间长度为1时,结果为0.从上至下,从左至右,区间长度有小到大一个一个遍历。进而得出整个大区间上最优解的dp算法。从下标i到下标j之间,最小的代价和。,求解一段区间上的最优解。原创 2023-03-04 11:34:26 · 508 阅读 · 0 评论 -
189、【动态规划】leetcode ——312. 戳气球(C++版本)
原题链接:312. 戳气球很多求最值实际上就是穷举所有情况,对比找出最值。因为不同的戳气球顺序会产生不一样的结果,所以实际上这就是一个全排列问题。此方式会超时此题和其他动态规划题的一个区别就是,、、相互有关,而动态规划算法使用的一个重要条件就是子问题需要相互独立。因此,为了可以使用动态规划,需要巧妙地定义数组,避免子问题产生相关性。因为,戳到最后时,也会左右乘上1,因此我们让的前后都加上1。(1)dp[i][j]含义:在到中可得到的最大硬币数(因为首尾新增了两个数,因此不戳首尾按开区间算)。(2)递推公原创 2023-03-03 11:02:28 · 443 阅读 · 0 评论 -
188、【栈与队列】leetcode ——84. 柱状图中最大的矩形:暴力解法+单调栈(C++/Python版本)
整体思路与 42. 接雨水 相近,区别在于接雨水的时候,单调栈是按从栈底到栈顶单调不增顺序存储,而本题要找到最大勾画面积,可以让每次到达一个比栈顶元素更低的长方体时,触发求面积的计算,也就是每当遇到右边第一个比自己更小的元素时,计算一次。因此,本体可按照单调栈从栈底到栈顶,单调不减的次序存储。采用单调栈的方式,自栈底到栈顶,按照单调不减的次序存储元素。每当第一次遇到比栈顶元素更小的数,则将栈顶元素弹栈,计算高度差和间隔差,得到面积,再和已有结果比较取最大值。注意:由于有可能输入数组会是单调递增数组,那么如果原创 2023-03-01 13:15:43 · 112 阅读 · 0 评论 -
187、【栈与队列】leetcode ——42. 接雨水(C++版本)
用单调栈来存储高度值,当为单调不增时入栈,当遇到的数比栈顶元素大时,就把栈顶元素弹出,计算当前栈顶元素可接的雨水体积。每遍历到一个高度时,就左右寻找探索两侧的边界,然后取二者中的最小值与当前高度相减(取最小值的原因,相当于是一个最短的木桶板决定了它最大可存水量的上界)。因此,寻找二者中的最小高度作为与栈顶元素的高度差,相减求出可接雨水高度。然后,再找出长度与之相乘,就可得到可接的雨水体积,也就是可接雨水个数。存储元素:数组下标,存储次序:从栈底到栈顶,单调不增(包含递减和等于的情况)。原创 2023-02-28 23:09:50 · 85 阅读 · 0 评论 -
186、【栈与队列】leetcode ——503. 下一个更大元素 II(C++版本)
核心思路相同,区别在于本题的数组变为循环数组,第一次遍历到前n个未找到更大数的数,还有后续循环会变会遍历到的可能情况。为考虑循环的影响,这里就有两个思路:一个是构造出一个数组二倍的数组,进行遍历。本题代码构建的重点就是维持好映射关系。原创 2023-02-28 10:51:24 · 72 阅读 · 0 评论 -
185、【栈与队列】leetcode ——496. 下一个更大元素 I:单调栈-哈希表(C++版本)
中想等元素时,就记录答案。如果没有遇到就进行正常的入栈,出栈操作。因此,第一步需要找到想等数,第二步需要找到大于的数。中下标,采用空间换时间的方式,避免两重for循环。方式,维持一个从栈底到栈顶的递减栈。对于第一步,我们可以用Hash表完成。对于第二步,就采用和每日温度相同的。的区别在于,需要先通过让。判定出为想等元素后,再去找。中想等元素的映射关系,存储。原创 2023-02-27 22:46:56 · 179 阅读 · 0 评论 -
184、【栈与队列】leetcode ——739. 每日温度(C++版本)
更直白来说,就是用一个栈来记录我们遍历过的元素,因为我们遍历数组的时候,我们不知道之前都遍历了哪些元素,以至于遍历一个元素找不到是不是之前遍历过一个更小的,所以我们需要用一个容器(这里用单调栈)来记录我们遍历过的元素。每次遍历到一个数时,就再开辟一个变量找此数后面第一个大于它的数,找到则添加,没找到则返回0。单调栈的本质是空间换时间,原创 2023-02-27 17:05:02 · 101 阅读 · 0 评论 -
【算法刷题】动态规划算法题型及方法归纳
动态规划中每一个状态一定是由上一个出来,根据这个特点,可以在过程中,存储某一条件下的数据,当再次遍历该条件时,直接取该条件对应的数据即可,可以避免重复计算,减少时间。原创 2023-02-25 22:01:30 · 1948 阅读 · 0 评论 -
183、【动态规划】leetcode ——516. 最长回文子序列(C++版本)
时,则尝试排除左端或右端元素,找到可以构成回文子序列的最大长度。从下标i到下标j之间,s具有的最大回文子序列长度。dp[i][i]=1,自身为最小回文串,其余为0。基础上,再加上这个两个相等的数,变为。两个状态,两个操作。从下到上,从左至右。原创 2023-02-25 21:55:38 · 253 阅读 · 0 评论 -
182、【动态规划/数组】leetcode ——647. 回文子串:动态规划+双指针(C++/Python版本)
判定是否为回文串。当子串为奇数长度时,回文串中心唯一;当子串为偶数长度时,会由两个数作为回文串中心。如此时子串长度超过2时,则需要根据上一次i与j之间的位置结果进行判定,若。dp[i][j] = false,都为进行判定时,为false。因为每次子串为从两边向中间伸缩,因此为从下至上,从左至右。bool类型变量,s中下标i到下标j之间是否为回文串。,则再加上当前的情况一定为回文串,执行。时,若此时子串的长度为1或2时(),此时一定为回文串,执行。动态规划的思路是每次判定。两个状态,三种操作。原创 2023-02-25 17:00:52 · 302 阅读 · 0 评论 -
181、【动态规划】leetcode ——72. 编辑距离(C++版本)
dp[i][0] = dp[0][i] = i,另一方为0时需要删除i次或修改i次。dp中的i对应word1中的i-1,dp中的j对应word2中的j-1。,直接由上一步转移过来。结尾子串,经过最少次增删改后,可让。从左到右,从上到下。原创 2023-02-24 21:22:51 · 461 阅读 · 1 评论 -
180、【动态规划】leetcode ——583. 两个字符串的删除操作:两种动态规划思路(C++版本)
的区别在于,1143中求的是两个序列中的最长公共子序列,而本题是要找到最少删除多少个元素后可以得到公共子序列。实际上,如果要找到删除元素最少,也就是要找到一个最长公共子序列,然后用两个序列的之和减去最长公共子序列长度的二倍,即可得到最少删除的元素个数。,分别试着删除一个和两个,由于前方删除一个的情况都已经含义删除两个时加上二的情况,所以只用写。以word1[i - 1]和word2[j - 1]为结尾的字符串,最少删除元素的个数。中相当于是只能删除一个字符串中的元素,而本题是两个字符串中的元素都可以删除。原创 2023-02-24 11:30:25 · 354 阅读 · 0 评论 -
179、【动态规划】leetcode ——115. 不同的子序列(C++版本)
相等时,可来源于s和t末尾对应的dp状态。由于要得到的是累积的个数,因此需要再加上保持目标串t不变,选择串s向前缩一位对应的dp状态。都不等时,保持目标串t的不变,选择串s向前缩一位的状态直接复制给不等的情况。dp[i][0] = 1,意为选择为空的时候,仅有一种情况(选择串中也什么都不选),dp[0][i] = 0,其中dp[0][0] = 1。的区别在于,选择串中可能会有多个目标串满足,因此要对满足目标串的进行累积计算。为结尾,字符串t为字符串s的子串个数。从左到右,从上到下。原创 2023-02-24 10:22:08 · 120 阅读 · 0 评论 -
178、【数组/动态规划】leetcode ——392. 判断子序列:双指针+动态规划(C++版本)
的时候,因为要求字符串s为t的子串,因此固定s末尾指向位置不动,让指向t的指针向前面移动一个,由此位置转移状态,即。由此方式,遍历完整个字符串。的时候,从上一个状态转移过来,的过程中,每遇到一个。指向元素相等时,则让。原创 2023-02-23 17:43:34 · 105 阅读 · 0 评论 -
177、【动态规划】leetcode ——11035. 不相交的线(C++版本)
问题转化:如果想要不相交的连接两两相同的数字,那么就要求按从左到右的顺序,递增找公共子序列。这样子问题就转化为了找到两个最长公共子序列。原创 2023-02-23 13:14:10 · 131 阅读 · 0 评论 -
176、【动态规划】leetcode ——1143. 最长公共子序列(C++版本)
因为i-1和j-1时不等,则取取消一个末尾后,二者中的继承的最大长度值。text2[j - 1]`结尾,具有的最长公共子序列。的区别在于此时不要求令一个数组中元素连续。,在上一个长度的基础上加一。以text1[i - 1]原创 2023-02-22 21:11:10 · 335 阅读 · 0 评论 -
175、【动态规划】leetcode ——718. 最长重复子数组 (C++版本)
dp[i][0] = dp[0][i] = 0,因为以i-1和j-1为结尾,故此时为无意义,因此设为0便于后续计算。结尾所具有的最长重复子数组长度。(以i-1而不以i为结尾的目的是可以简化代码),满足两者在i和j处相等时,就以。的基础上再加一个长度。原创 2023-02-22 19:28:39 · 99 阅读 · 0 评论 -
174、【动态规划/贪心算法/滑动窗口】leetcode ——674. 最长连续递增序列:一题多解 (C++版本)
dp[i] = dp[i - 1] + 1,每遇到一个连续的字符,就在上一个已有的最长子序列长度上加一。dp[i] = 1,自身最少为一个。从下标i往前的最长连续子序列长度。原创 2023-02-21 21:33:43 · 127 阅读 · 0 评论 -
173、【动态规划】leetcode ——300. 最长递增子序列 (C++版本)
从之前已有结果,和现在发现情况找到一个最大值。因位找到是递增序列,那么若j-i为递增序列,则i在比。外层从小到大遍历,内从每次从0位置开始遍历更新,每遍历到。外层只能从小到大,内层从小到大或从大到小都可以。dp[i] = 1,因为最少为自身一个。下标0-i之间,最大子序列长度。下标元素大时,一定也会比。原创 2023-02-21 17:03:19 · 152 阅读 · 0 评论 -
172、【动态规划】leetcode ——714. 买卖股票的最佳时机含手续费 (C++版本)
因为会有扣除手续费,可能会导致卖出去后扣得费用更多所以返回这两个中的最大值。的区别在于含有一个收费,只需要在最后卖出时候扣除手续费后再比较即可。,也就是上一次没有卖的时候和这次进行买卖后比较出最大值。注意:最后返回的可以不为。原创 2023-02-20 18:49:53 · 94 阅读 · 0 评论 -
171、【动态规划】leetcode ——309. 最佳买卖股票时机含冷冻期 (C++版本)
dp[0][0] = -prices[0],因为不能当天买当天卖dp[0][1] = dp[0][2] = dp[0][3]为非法变量,为了便于后续计算,由后续的需求可反推知,应把这三个初始化为0。:取三种操作的最大值。第二种,昨天不持有并且昨天不为冷冻期,今天买入股票。第一种,之前已不持有且昨天不为冷冻期,保持。第二种,之前已不持有并且昨天为冷冻期,从冷冻期转移过来。:今天不持有股票并且明天不为冷冻期时,最大收益。:持有股票时的最大收益,在之前的就已持有的状态和从非冷冻期后当天买入的状态中,去最大值。原创 2023-02-20 18:27:00 · 772 阅读 · 0 评论 -
170、【动态规划】leetcode ——188. 买卖股票的最佳时机 IV:二维数组+一维数组 (C++版本)
dp[i][2 * k - 1] = 第i天第k次已持有股票时的最大总收益 = max(第i-1天第k次已持有股票时的最大总收益,第i天第k次已持有股票时的最大总收益(第i-1天第k - 1次不持有股票时的最大总收益 - prices[i]))dp[i][2 * k] = 第i天第k次已不持有股票时的最大总收益 = max(第i-1天第k次已不持有股票时的最大总收益,第i天第k次已不持有股票时的最大总收益(第i-1天第k次已持有股票时的最大总收益 + prices[i]))但处理逻辑还是与之前相同。原创 2023-02-18 20:40:48 · 150 阅读 · 0 评论 -
169、【动态规划】leetcode ——123. 买卖股票的最佳时机 III:二维数组+一维数组 (C++版本)
dp[i][3] = max(dp[i - 1][3], dp[i][2] + prices[i]),表示在之前已第二次不持有股票和第i天第二次持有股票中,找一个最大值,作为最大收益。dp[i][2] = max(dp[i - 1][2], dp[i][1] + prices[i]),表示在之前已第一次不持有股票和第i天把股票售出后中,找一个最大值,作为最大收益。,每次到第i次遍历时,max中的dp[1]就相当于是第i-1次时计算得到的结果,取完最大值后,dp[1]就变为了dp[i][1]原创 2023-02-18 13:55:13 · 463 阅读 · 0 评论 -
168、【动态规划】leetcode ——121. 买卖股票的最佳时机:dp数组+变量优化 (C++版本)
dp[i][1] = max(dp[i - 1][1], prices[i] - dp[i - 1][0]),由于是不持有股票,因此也会有两种情况。一种是之前不持有时的收益情况(可能已经进行过一次买卖交易,也可能一直没有买入过),另一种是现在将已有股票售出,就用当前卖出的价格减去之前最小买入的价格。dp[i][0] = min(dp[i - 1][0], prices[i]),由于是持有股票,因此可能会有两种情况。dp[0][0] = -prices[0],刚开始买入第一天买入的情况。原创 2023-02-17 13:08:10 · 161 阅读 · 0 评论 -
167、【动态规划】AcWing ——83. 股票的最大利润 (C++版本)
因为利润最大化时,一定是一个数最大,另一个是在这个最大数前方的最小数。用来记录在遍历到i时,前i-1个变量中的最小值。每轮遍历都取当前可得到的最大利润。因此,维持两个变量,一个变量。找到整体的最大利润。用来记录结果,一个变量。原创 2023-02-17 12:23:14 · 286 阅读 · 0 评论 -
165、【动态规划】leetcode ——337. 打家劫舍 III:记忆化递归+动态规划(C++版本)
因为dp数组是从小到大,大的要基于小的结果去进行操作。所以,需要使用后序遍历的方式,左右中的顺序遍历。底层的结果返回给上一层,上一层处理完后再返回给其上一层。对左右遍历完后,用val1记录不偷时的情况,找出偷下一个结点值更大,还是不偷下一个结点值更大。用val2记录偷时的情况,当前结点加上不偷下一个结点时的情况。,返回值为长度为2的dp数组,下标0表示不偷root的结果,下标1表示偷root的结果。当遍历到该节点时,判定之前是否遍历过,如果遍历过,直接返回。最终,找到二者之间的最大值,返回。原创 2023-02-16 20:15:04 · 308 阅读 · 0 评论