- 博客(168)
- 收藏
- 关注
原创 代码随想录|图论|09沉没孤岛
这道题跟求孤岛面积很像,我们还是从边缘的岛屿来考虑,把边缘的岛屿全部做上标记(不是0和1,这里用2来表示它是靠边的,不是中间的),然后遍历整个网格,如果遇到了1,说明就是中间的孤岛,把它变成0.给定一个由 1(陆地)和 0(水)组成的矩阵,岛屿指的是由水平或垂直方向上相邻的陆地单元格组成的区域,且完全被水域单元格包围。现在你需要将所有孤岛“沉没”,即将孤岛中的所有陆地单元格(1)转变为水域单元格(0)。之后 N 行,每行包含 M 个数字,数字为 1 或者 0,表示岛屿的单元格。
2025-06-27 20:20:27
212
原创 代码随想录|图论|08孤岛的总面积
题目题目题目描述给定一个由 1(陆地)和 0(水)组成的矩阵,岛屿指的是由水平或垂直方向上相邻的陆地单元格组成的区域,且完全被水域单元格包围。孤岛是那些位于矩阵内部、所有单元格都不接触边缘的岛屿。现在你需要计算所有孤岛的总面积,岛屿面积的计算方式为组成岛屿的陆地的总数。输入描述第一行包含两个整数 N, M,表示矩阵的行数和列数。之后 N 行,每行包含 M 个数字,数字为 1 或者 0。输出描述输出一个整数,表示所有孤岛的总面积,如果不存在孤岛,则输出 0。输入示例输出示例:1思路。
2025-06-27 19:53:32
262
原创 代码随想录|图论|07岛屿的最大面积
题目题目题目描述给定一个由 1(陆地)和 0(水)组成的矩阵,计算岛屿的最大面积。岛屿面积的计算方式为组成岛屿的陆地的总数。岛屿由水平方向或垂直方向上相邻的陆地连接而成,并且四周都是水域。你可以假设矩阵外均被水包围。输入描述第一行包含两个整数 N, M,表示矩阵的行数和列数。后续 N 行,每行包含 M 个数字,数字为 1 或者 0,表示岛屿的单元格。输出描述输出一个整数,表示岛屿的最大面积。如果不存在岛屿,则输出 0。输入示例输出示例4思路需要计算每一个岛屿群的面积,然后找出最大的。
2025-06-27 19:11:33
76
原创 代码随想录|图论|05岛屿数量(深搜DFS)
给定一个由 1(陆地)和 0(水)组成的矩阵,你需要计算岛屿的数量。岛屿由水平方向或垂直方向上相邻的陆地连接而成,并且四周都是水域。我这里写的是dfs的第二个模板,第一个模版因为没有终止条件,所以写起来感觉很奇怪,我就没有放,感兴趣去看随想录。后续 N 行,每行包含 M 个数字,数字为 1 或者 0。输出一个整数,表示岛屿的数量。第一行包含两个整数 N, M,表示矩阵的行数和列数。遇到一个没有遍历过的节点陆地,计数器就加一,然后把。在遇到标记过的陆地节点和海洋节点的时候直接跳过.计数器就是最终岛屿的数量。
2025-06-26 20:16:28
294
原创 代码随想录|图论|04广度优先搜索理论基础
广搜的搜索方式就适合于解决两个点之间的最短路径问题。因为广搜是从起点出发,以起始点为中心一圈一圈进行搜索,一旦遇到终点,记录之前走过的节点就是一条最短路。当然,也有一些问题是广搜 和 深搜都可以解决的,例如岛屿问题,。(我们会在具体题目讲解中详细来说)比如下面这个图,从start开始慢慢向外扩展,第4次扩展才到end,那么最短路径的长度就是4,一旦遇到终止点,那么一定是一条最短路径。
2025-06-26 19:33:16
199
原创 代码随想录|图论|03所有可达路径
题目题目【题目描述】给定一个有 n 个节点的有向无环图,节点编号从 1 到 n。请编写一个程序,找出并返回所有从节点 1 到节点 n 的路径。每条路径应以节点编号的列表形式表示。【输入描述】第一行包含两个整数 N,M,表示图中拥有 N 个节点,M 条边后续 M 行,每行包含两个整数 s 和 t,表示图中的 s 节点与 t 节点中有一条路径【输出描述】输出所有的可达路径,路径中所有节点的后面跟一个空格,每条路径独占一行,存在多条路径,路径输出的顺序可任意。
2025-06-25 18:23:43
602
原创 代码随想录|图论|01图论基础
一般有n的节点的情况下,需要设置一个 n+1*n+1 大小的邻接矩阵matrix,因为直接用节点数字表示索引比较方便。这种表达方式在节点多、边少的情况下,会申请过大的二维数组,造成空间浪费,所以说适合稠密图,不适合稀疏图。邻接表是“数组+链表”的形式,从边出发,对于每个节点来说,有多少条边,就申请多长的链表。比如grid[2][5] = 6,grid[5][2] = 6,表示无向图,权值为6;有向图:根据连接这个节点的线,指向箭头的是入度,指出箭头的是出度。有向图是拓扑排序的基本。
2025-06-24 18:35:57
271
原创 代码随想录|单调栈|05柱状图中的最大矩形
题目题目给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1。求在该柱状图中,能够勾勒出来的矩形的最大面积。思路。
2025-06-23 21:02:58
313
原创 代码随想录|单调栈|04接雨水
题目题目给定n个非负整数表示每个宽度为1的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。6上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。9思路听说这是字节最简单的题。
2025-06-23 19:40:14
907
原创 代码随想录|单调栈|03求下一个更大的元素II
给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1。这里数组变成了循环数组,我最开始想得是把数组复制一个,然后拼接在后面。单调栈找右边第一个比它大的元素,全部套“每日温度”这个题的模版。其实也不需要再去新建一个数组,而是通过。比如原来的数组是【1 2 1】的方式去便利这个环形数组。
2025-06-09 21:18:26
193
原创 代码随想录|单调栈|02下一个更大元素I
为什么需要构建映射逻辑,因为我们用nums2构建单调栈,但是在计算result的时候,是要看nums1的元素,所以在nums2中准备添加result时候,要看一下这个元素在不在nums1里面,如果在的话,就添加到相应的位置。nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。对于 num1 中的数字 4 ,你无法在第二个数组中找到下一个更大的数字,因此输出 -1。对于 num1 中的数字 2 ,第二个数组中没有下一个更大的数字,因此输出 -1。
2025-06-09 20:36:40
322
原创 代码随想录|单调栈|1每日温度
例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。i=1,T[i]=74,因为74>73,所以弹出top放入i,同时可以计算result[top]=i-top,此时top=74。i=2,T[i]=75,因为75>74,所以弹出top放入i,同时可以计算result[top]=i-top,此时top=75。这里单调栈里面存的是索引,而不是元素,因为要计算索引之间的差值。
2025-06-08 21:44:42
341
原创 代码随想录|动态规划|53最长回文子序列
根据dp的定义,可以知道j一定是大于等于i的,而i=j的情况是我们在初始化定义的,所以地推的时候j要从i+1开始。如果s[i] = s[j],就看里面的子序列,此时dp[i][j] = dp[i+1][j-1] + 2。[i,i]是回文的,所以dp[i][i]=1,其他的就初始化为0,因为确实不知道到底是不是回文。如果s[i] ≠ s[j],就要考虑[i,j-1] [i+1,j] 这两种情况,取最大的值。示例 1: 输入: "bbbab" 输出: 4 一个可能的最长回文子序列为 "bbbb"。
2025-06-07 21:44:37
393
原创 代码随想录|动态规划|52回文子串
dp如何定义,这里不能像之前那样,定义成以i为结尾什么的,假如说定义dp[i]是以i为结尾的回文数组,但是发现是很难找到递推关系的。(3)i ≠ j的条件下,dp[i][j]=false,所以初始化都给它定义为false,然后在循环里面就直接不用考虑这个情况了。具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。注意是只有左下角,左边和下面都没有,所以在第二层循环的时候,j要从i开始。dp[i][j]表示[i,j]的子串是回文子串。dp的定义,是根据回文子串的性质来写的。
2025-06-07 21:18:58
316
原创 代码随想录|动态规划|50编辑距离
解释: intention -> inention (删除 't') inention -> enention (将 'i' 替换为 'e') enention -> exention (将 'n' 替换为 'x') exention -> exection (将 'n' 替换为 'c') exection -> execution (插入 'u')以[i-1]结尾的word1和以[j-1]结尾的word2,最近的编辑距离是dp[i][j]word1删:dp[i][j]=dp[i-1][j]+1。
2025-06-04 22:09:05
547
原创 代码随想录|动态规划|49两个字符串的删除操作
题目题目给定两个单词 word1 和 word2,找到使得 word1 和 word2 相同所需的最小步数,每步可以删除任意一个字符串中的一个字符。思路本题和“不同的子序列”相比,就是两个子序列都可以进行删除操作。动归五部曲(1)dp含义dp[i][j]:以i-1为结尾的字符串word1,和以j-1位结尾的字符串word2,想要达到相等,所需要删除元素的最少次数。(2)递推公式。
2025-06-04 21:33:06
392
原创 代码随想录|动态规划|48不同的子序列
一部分是用s[i - 1]来匹配,那么个数为dp[i - 1][j - 1]。当s[i - 1] 与 t[j - 1]不相等时,dp[i][j]只有一部分组成,不用s[i - 1]来匹配(就是模拟在s中删除这个元素)所以当s[i - 1] 与 t[j - 1]相等时,dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j]dp[i][j]:以i-1为结尾的s子序列中出现以j-1为结尾的t的个数为dp[i][j]。所以 dp[i][j] = dp[i-1][j]
2025-06-02 21:38:09
402
原创 代码随想录|动态规划|47判断子序列
(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。如果s[i - 1] == t[j - 1],那么这两段子序列最后一个字符相同,同时去掉最后这个字符,然后再找公共子序列长度,最后+1。dp[i][j] 表示以下标i-1为结尾的字符串s,和以下标j-1为结尾的字符串t,相同子序列的长度为dp[i][j]。当时写的是 max(dp[i - 1][j], dp[i][j - 1])给定字符串 s 和 t ,判断 s 是否为 t 的子序列。t的长度要比s更长,所以只写dp[i][j - 1]
2025-06-02 20:56:08
368
原创 代码随想录|动态规划|46最大子序和
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。贪心之前做过,这里用动态规划还是更为简单。
2025-06-01 20:10:43
125
原创 代码随想录|动态规划|45不相交的线
直线不能相交,这就是说明在字符串nums1中 找到一个与字符串nums2相同的子序列,且这个子序列不能改变相对顺序,只要相对顺序不改变,连接相同数字的直线就不会相交。在两条独立的水平线上按给定的顺序写下 nums1 和 nums2 中的整数。第一眼看真的不清楚,这种就是在基础题上面套了应用的外壳,但是自己看不出来😅。请注意,连线即使在端点也不能相交:每个数字只能属于一条连线。以这种方法绘制线条,并返回可以绘制的最大连线数。就是跟上面的 “最长公共子序列” 是一样的。代码也是一样的,就是变量名字换了。
2025-06-01 19:59:23
233
原创 代码随想录|动态规划|44最长公共子序列
上一题因为是连续的,所以如果A[i-1][j-1]≠B[i-1][j-1],对于dp[i][j]没有影响。根据dp[i][j]的定义,dp[i][j]的状态只能由dp[i - 1][j - 1]推导出来。那么dp[i][j] = max(dp[i][j-1] , dp[i-1][j])(为什么是i-1 j-1在之前已经解释过了,为了方便初始化)所以如果A[i-1][j-1]≠B[i-1][j-1]如果A[i-1][j-1]==B[i-1][j-1]那么dp[i][j]=dp[i-1][j-1]+1。
2025-05-31 22:32:55
413
原创 代码随想录|动态规划|43最长重复子数组
dp[i][j] :以下标i - 1为结尾的A,和以下标j - 1为结尾的B,最长重复子数组长度为dp[i][j]。但是为了递推公式还是需要初始化的,dp[i][0] 和 dp[0][j]都初始化为0即可,不会影响到后面的递推。根据dp[i][j]的定义,dp[i][0] 和dp[0][j]其实都是没有意义的。dp[1][1] = dp[0][0] + 1,结果应该是1。那么i的范围是[1,lenA],j的范围是[1,lenB]那么dp[i][j]=dp[i-1][j-1]+1。所以dp[0][0]=0。
2025-05-22 11:38:00
304
原创 代码随想录|动态规划|42最长连续递增子系列
连续递增的子序列 可以由两个下标 l 和 r(l < r)确定,如果对于每个 l <= i < r,都有 nums[i] < nums[i + 1] ,那么子序列 [nums[l], nums[l + 1], ..., nums[r - 1], nums[r]] 就是连续递增子序列。给定一个未经排序的整数数组,找到最长且 连续递增的子序列,并返回该序列的长度。跟上面一道题的区别在于,这里是连续的,也就是如果dp[i]>dp[i-1]那么dp[i]=dp[i-1]+1。
2025-05-22 11:03:39
396
原创 代码随想录|动态规划|41最长上升子系列
子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。位置i的最长升序子序列等于j从0到i-1各个位置的最长升序子序列 + 1 的最大值。给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。每一个i,对应的dp[i](即最长递增子序列)起始大小至少都是1。外层是i,内层是j,j的范围是[0,i),所以i从1开始就可以。,可以跳,但是顺序维持原数组顺序!
2025-05-22 10:54:10
561
原创 代码随想录|动态规划|39买卖股票的最佳时机含手续费
给定一个整数数组 prices,其中第 i 个元素代表了第 i 天的股票价格;非负整数 fee 代表了交易股票的手续费用。你可以无限次地完成交易,但是你每笔交易都需要付手续费。如果你已经购买了一个股票,在卖出它之前你就不能再继续购买股票了。注意:这里的一笔交易指买入持有并卖出股票的整个过程,每笔交易你只需要为支付一次手续费。在卖出股票的时候,需要减去手续费。dp[i][1] 第i天不持有股票。dp[i][0] 第i天持有股票。看到这里就总结一下股票问题吧。返回获得利润的最大值。
2025-05-20 10:49:49
140
原创 代码随想录|动态规划|37买卖股票最佳时机含冷冻期
dp[i][1] 不持有股票状态,保持卖出股票的状态(两天前就卖出了股票,度过一天冷冻期。由于dp[0][0]=dp[0][1]-prices[1],第1天买入股票,那么第0天的现金默认是0,dp[i][0] 持有股票状态(今天买入股票,或者是之前就买入了股票然后没有操作,一直持有)。dp[i][j],第i天状态为j,所剩的最多现金为dp[i][j]。dp[i][3] 今天为冷冻期状态,但冷冻期状态不可持续,只有一天!dp[i][2] 不持有股票状态,今天卖出股票。所以dp[0][1]=0。
2025-05-20 10:41:58
363
原创 代码随想录|动态规划|36买卖股票的最佳时机IV
输出:7 解释:在第 2 天 (股票价格 = 2) 的时候买入,在第 3 天 (股票价格 = 6) 的时候卖出, 这笔交易所能获得利润 = 6-2 = 4。随后,在第 5 天 (股票价格 = 0) 的时候买入,在第 6 天 (股票价格 = 3) 的时候卖出, 这笔交易所能获得利润 = 3-0 = 3。输出:2 解释:在第 1 天 (股票价格 = 2) 的时候买入,在第 2 天 (股票价格 = 4) 的时候卖出,这笔交易所能获得利润 = 4-2 = 2。输入:k = 2, prices = [2,4,1]
2025-05-19 16:38:08
787
原创 代码随想录|动态规划|35买卖股票的最佳时机III
输出:6 解释:在第 4 天(股票价格 = 0)的时候买入,在第 6 天(股票价格 = 3)的时候卖出,这笔交易所能获得利润 = 3-0 = 3。随后,在第 7 天(股票价格 = 1)的时候买入,在第 8 天 (股票价格 = 4)的时候卖出,这笔交易所能获得利润 = 4-1 = 3。输出:4 解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4。输入:prices = [3,3,5,0,0,3,1,4]
2025-05-19 11:03:53
485
原创 代码随想录|动态规划|34买卖股票的最佳时机II
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4。解释: 在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4。所以dp[i][0]=max(dp[i-1][0],dp[i-1][1]-prices[i])所以dp[i][1]=max(dp[i-1][1],dp[i-1][0]+prices[i])输入: [7,1,5,3,6,4]
2025-05-16 14:27:52
861
原创 代码随想录|动态规划|32买卖股票的最佳时机
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5。给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。dp[0][0]=-prices[0],因为第一天就买了,但是本来手头上最大金钱为0,这样相当于贷款。在遍历的过程中计算dp[i][0]和dp[i][1],最终的结果只要dp[len-1][1]?dp[0][1]=0,第一天不买,手头上就是0。(1)dp[i][0] 表示第i天。
2025-05-16 11:44:52
628
1
原创 代码随想录|动态规划|31打家劫舍III
之前打家劫舍的问题,我们最后求的是dp[nums.size()-1]也就是偷最后一个房子的最大金钱,那么这里按照后序遍历,可以把root根节点看作是最后的房子。这里不可以再用i去代表每一个状态的下标了,因为是二叉树,不是数组,二叉树有自己的遍历方式。树形dp,dp数组的形式真的没想到还能这样子写,归根还是在于数组跟树的遍历区别,树的遍历一定是那3种遍历顺序的,你用下标i根本无法表示。父节点一定和子节点连着的,所以相邻的节点不可以都偷,只能隔着偷。通过递归左节点,得到左节点偷与不偷的金钱。
2025-04-06 12:56:22
583
原创 代码随想录|动态规划|30打家劫舍II
你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。解释:你可以先偷窃 1 号房屋(金额 = 1),然后偷窃 3 号房屋(金额 = 3)。解释:你不能先偷窃 1 号房屋(金额 = 2),然后偷窃 3 号房屋(金额 = 2), 因为他们是相邻的。当然情况2、3实际上包含了情况1,比如情况2,我只是考虑了首元素,没说一定要选啊。输入:nums = [1,2,3,1]输入:nums = [2,3,2]
2025-04-06 12:11:37
444
原创 代码随想录|动态规划|29打家劫舍
解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。然后dp[i]取最大值,即dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);(1)dp[i]:考虑下标i(包括i)以内的房屋,最多可以偷窃的金额为dp[i]。如果偷第i房间,那么dp[i] = dp[i - 2] + nums[i]如果不偷第i房间,那么dp[i] = dp[i - 1],即考虑i-1房,((3)递推公式有i-2和i-1,所以初始化应该考虑dp[0]和dp[1]。
2025-04-06 12:09:51
339
原创 代码随想录|动态规划|26单词拆分
(2)如果确定dp[j] 是true,且 [j, i] 这个区间的子串出现在字典里,那么dp[i]一定是true。给定一个非空字符串 s 和一个包含非空单词的列表 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。(1)dp[i]: 字符串长度为i的话,dp[i]为true,表示可以拆分为一个或多个在字典中出现的单词。(4)dp[0]一定为true,不然后面根据递推公式会一直为false。从小到大逐渐找s的子串,看子串是不是数组里面的元素。你可以假设字典中没有重复的单词。
2025-04-04 16:30:48
262
原创 代码随想录|动态规划|24完全平方数
(3)dp[0]表示 和为0的完全平方数的最小数量,本来写的是1,但是题目要求n>=1,所以这里j=0只是为了递推公式好写,实际上是dp[0]=0。(1)dp[j]:填满容量为j的背包,需要的最少物品个数。(和为j的完全平方数的最小个数)物品:i从0开始,最大满足i*i<=n。(4)求个数,不考虑遍历的顺序。转换成背包问题之后就很好写了。原问题转换为完全背包问题。背包容量:n,需要填满。物品的容量:i*i。
2025-04-04 15:35:33
286
原创 代码随想录|动态规划|23零钱兑换
(2)如果包含coins[i],凑足总额为j - coins[i]的最少个数为dp[j - coins[i]],那么只需要加上一个钱币coins[i]即dp[j - coins[i]] + 1就是dp[j]。考虑到递推公式的特性,dp[j]必须初始化为一个最大的数,否则就会在min(dp[j - coins[i]] + 1, dp[j])比较的过程中被初始值覆盖。递推公式:dp[j] = min(dp[j - coins[i]] + 1, dp[j]);所以下标非0的元素都是应该是最大值。
2025-04-04 15:14:19
279
原创 代码随想录|动态规划|21组合总和IV
所有可能的组合为: (1, 1, 1, 1) (1, 1, 2) (1, 2, 1) (1, 3) (2, 1, 1) (2, 2) (3, 1)给定一个由正整数组成且不存在重复数字的数组,找出和为给定目标正整数的组合的个数。递推公式为 dp[j] += dp[j-nums[i]];排列强调排序顺序,所以先遍历背包,再遍历物品。物品就是nums数组的每一个元素nums[i]这里跟上面那道题的区别在于 “排列!请注意,顺序不同的序列被视作不同的组合。物品对应的容量也是nums[i]
2025-04-03 20:38:25
196
原创 代码随想录|动态规划|19零钱兑换II
(1)dp[i][j]:使用 下标为[0, i]的coins[i]能够凑满j(包括j)这么大容量的包,有dp[i][j]种组合方法。那么就是先把1加入计算,然后再把5加入计算,得到的方法数量只有{1, 5}这种情况。背包容量的每一个值,都是经过 1 和 5 的计算,包含了{1, 5} 和 {5, 1}两种情况。第一列:背包容量为0,就是啥也装不了,就一种方法,即dp[i][0]=1.假设:coins[0] = 1,coins[1] = 5。(1)dp[j]:凑成总金额j的货币组合数为dp[j]
2025-04-03 20:27:40
1011
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人